赋值运算符应该注意的细节
时间:2010-09-19 来源:zyd_cu
C++的设计者Bjarne Stroustrup下了很大的功夫想使用户自定义类型尽可能地和固定类型的工作方式相似,这就是为什么你可以重载运算符,写类型转换函数,控制赋值和拷贝构造函数。
对于类类型,当重载赋值运算符时,需注意以下几个原则:
1. operator=尽量返回*this的引用;
2. 在operator=中对所有的数据成员赋值;
3. 在operator=中检查给自己赋值的情况;
对于普通的类型,int w, x, y, z; w = x = y = z = 0; 这样的串联赋值相当于把w、x、y、z都赋值为0了,其相当于w = (x = (y = (z = 0))); 对于类类型,如果要支持这样的串联赋值,则需要在实现operator=时,返回对赋值对象的引用(这样的开销是最小的),即应该是:
C& C::operator=(const C&) { … return *this; }
在最初对某个类实现operator=时,我们通常能做到对每个数据成员赋值,但当类升级(增加了成员)或作为其他类的基类时,operator=的“升级”可能会被遗忘,从而导致程序出现不可预知的问题,派生类中的operator=需要显式的调用基类的operator=或直接对基类的成员进行赋值。
operator在实现时不考虑对自己赋值的情况,可能引发灾难性的问题,如http://blog.chinaunix.net/u2/87570/showart_2330861.html中的String类,operator=的实现是先把目标旧的数据清理掉(存储空间被释放),并申请新的空间存储数据,如果程序中出现a = a(a为String类对象),则a的空间先会被释放,接着再拷贝a的数据,而此时a中已无数据,从而对程序产生致命的影响。可在实现operator=时,进行如下两种方式的检查:
/* 这种判断方式更广泛的被使用 */ |