[align=center][size=large][b]Operator=[/b][/size][/align]
赋值构造函数,问题1:为何返回类型是类,即return *this;
问题2:为何要对自身判断,怎么判断以防止赋值给自己?
问题3:自己定义赋值构造函数,要对那些数据赋值?
带着这些问题,看看下面的例子:
[b]问题1:为何返回类型是类,即return *this;[/b]
这个例子可以通过编译,但是不能运行,原因何在?
此赋值构造函数为:
void operator=(const String& rhs);
注意返回类型为void,那么c = b = a;就会出错。
因为c = b = a;等价于c.operator=(b.operator=(a.operator=("hello"))); operator=结合性由右向左,a.operator=("hello")结果是:a.data = "hello";但是a.operator=("hello")经过赋值构造函数后并没有返回值,就无法在继续赋值给b。
因此赋值构造函数必需有返回值,且返回值为类本身的引用。
其正确的赋值构造函数写法如下:
[b]问题2:为何要对自身判断,怎么判断以防止赋值给自己?[/b]
上面的例子:若赋值构造函数为:
当执行到语句:a = a;就会出现问题:
*this data ------------> "hello\0"
/
/
rhs data -----
赋值运算符做的第一件事是用delete删除data,其结果将如下所示:
*this data ------------> ???
/
/
rhs data -----
现在,当赋值运算符对rhs.data调用strlen时,结果将无法确定。这是因为data被
删除的时候rhs.data也被删除了,data,this->data 和rhs.data 其实都是同一个
指针!从这一点看,情况只会越变越糟糕。
现在可以知道,解决问题的方案是对可能发生的自己给自己赋值的情况先进行检查
,如果有这种情况就立即返回.
[color=red]问题是如何判断两个对象“相同”??[/color]
确定对象身份是否相同的方法是用内存地址。采用这个定义,两个对象当且
仅当它们具有相同的地址时才是相同的。这个定义在c++程序中运用更广泛,可能
是因为它很容易实现而且计算很快。
其判断形势为:
if(this == &rhs)
return *this;
[b]问题3:自己定义赋值构造函数,要对那些数据赋值?[/b]
赋值构造函数,问题1:为何返回类型是类,即return *this;
问题2:为何要对自身判断,怎么判断以防止赋值给自己?
问题3:自己定义赋值构造函数,要对那些数据赋值?
带着这些问题,看看下面的例子:
[b]问题1:为何返回类型是类,即return *this;[/b]
#include <iostream>
using namespace std;
class String {
public:
String();
String(const char *value); // 函数定义参见条款11
~String(); // 函数定义参见条款11
void operator=(const String& rhs);
void Print() const;
private:
char *data;
};
String::String( const char *value )
{
if (value) {
data = new char[strlen(value) + 1];
strcpy(data, value);
}
else {
data = new char[1];
*data = '\0';
}
}
String::String()
{
data = new char[1];
*data = '\0';
}
String::~String()
{
//delete [] data;
}
void String::operator=( const String& rhs )
{
delete [] data;
//allocate new memory
data = new char[sizeof(rhs.data)+1];
strcpy(data,rhs.data);
//return *this;
}
void String::Print() const
{
cout << "The content is :" << data << endl;
}
int main()
{
String a = "hello";
String b = "world";
String c = "hewei";
a.Print();
c = b = a;
b.Print();
return 0;
}
这个例子可以通过编译,但是不能运行,原因何在?
此赋值构造函数为:
void operator=(const String& rhs);
注意返回类型为void,那么c = b = a;就会出错。
因为c = b = a;等价于c.operator=(b.operator=(a.operator=("hello"))); operator=结合性由右向左,a.operator=("hello")结果是:a.data = "hello";但是a.operator=("hello")经过赋值构造函数后并没有返回值,就无法在继续赋值给b。
因此赋值构造函数必需有返回值,且返回值为类本身的引用。
其正确的赋值构造函数写法如下:
String& operator=(const String& rhs);
String& String::operator=( const String& rhs )
{
if(this == &rhs)
return *this;
delete [] data;
//allocate new memory
data = new char[sizeof(rhs.data)+1];
strcpy(data,rhs.data);
return *this;
}
[b]问题2:为何要对自身判断,怎么判断以防止赋值给自己?[/b]
上面的例子:若赋值构造函数为:
String& operator=(const String& rhs);
String& String::operator=( const String& rhs )
{
//if(this == &rhs)
// return *this;
delete [] data;
//allocate new memory
data = new char[sizeof(rhs.data)+1];
strcpy(data,rhs.data);
return *this;
}
当执行到语句:a = a;就会出现问题:
*this data ------------> "hello\0"
/
/
rhs data -----
赋值运算符做的第一件事是用delete删除data,其结果将如下所示:
*this data ------------> ???
/
/
rhs data -----
现在,当赋值运算符对rhs.data调用strlen时,结果将无法确定。这是因为data被
删除的时候rhs.data也被删除了,data,this->data 和rhs.data 其实都是同一个
指针!从这一点看,情况只会越变越糟糕。
现在可以知道,解决问题的方案是对可能发生的自己给自己赋值的情况先进行检查
,如果有这种情况就立即返回.
[color=red]问题是如何判断两个对象“相同”??[/color]
确定对象身份是否相同的方法是用内存地址。采用这个定义,两个对象当且
仅当它们具有相同的地址时才是相同的。这个定义在c++程序中运用更广泛,可能
是因为它很容易实现而且计算很快。
其判断形势为:
if(this == &rhs)
return *this;
[b]问题3:自己定义赋值构造函数,要对那些数据赋值?[/b]