类的四个默认成员函数->赋值运算符重载函数
4.赋值运算符重载函数
1.函数的作用,参数和返回值
1.作用
赋值运算符重载函数用于类对象的赋值操作,当我们未实现该函数时,编译器会自动为我们实现该函数。
2.参数
赋值运算符重载函数的参数是常引用类型的类类型,声明为常量的好处是可以接受常量参数和非常量参数,
声明为引用类型使得参数没有了临时对象的生成,减少了一次拷贝构造的发生
3.返回值
大部分人(包括Effective C++)认为赋值运算符重载函数的返回值为引用类型的*this,这样可以实现支持赋值的连锁形式。举个栗子:
class A { public: A(){} A(int _a,int _b) : a(_a),b(_b){} A &operator =(const A&rhs) { this->a = rhs.a; this->b = rhs.b; return *this; } public: int a; int b; }; int main() { A j(12,13); A k,l; k = l = j; cout << j.a << "," << j.b << endl; cout << k.a << "," << k.b << endl; cout << l.a << "," << j.b << endl; return 0; }
测试结果:12,13
12,13
12,13
那么,这种说法是否正确呢?我们来做测试。
class B { public: B(){} B(int _a,int _b) : a(_a),b(_b){} B operator =(const B&rhs) { this->a = rhs.a; this->b = rhs.b; return *this; } public: int a; int b; }; int main() { B j(12,13); B k,l,n; //n = k = l = j = B(90,80); n = k = l = j; cout << j.a << "," << j.b << endl; cout << k.a << "," << k.b << endl; cout << l.a << "," << j.b << endl; cout << n.a << "," << n.b << endl; return 0; }
测试结果:
12,13
12,13
12,13
12,13
测试结果表明,赋值运算符重载函数并不需要返回值为引用类型,也可以完成连续赋值。那么,返回值为引用类型有什么好处呢?
如果返回值不是引用,在赋值操做中,必然会产生临时对象来完成对象的赋值操作。看代码
class B { public: B(){} B(const B&rhs) { this->a = rhs.a; this->b = rhs.b; std::cout << "copy constructors" << std::endl; } B(int _a,int _b) : a(_a),b(_b){} B operator =(const B&rhs) { this->a = rhs.a; this->b = rhs.b; return *this; } public: int a; int b; }; int main() { B j(12,13); B k,l,n; //n = k = l = j = B(90,80); n = k = l = j; cout << j.a << "," << j.b << endl; cout << k.a << "," << k.b << endl; cout << l.a << "," << j.b << endl; cout << n.a << "," << n.b << endl; return 0; }
测试结果:
copy constructors
copy constructors
copy constructors
12,13
12,13
12,13
12,13
注:此栗子经过vs2010与gcc共同测试,结果相同!!!
我们注意到,当返回值类型不为引用类型时,会产生临时对象,这样就会产生拷贝构造的多次调用,浪费了空间和效率!!!
所以,赋值运算符的重载不一定是引用类型也可以实现类对象的连续赋值,但返回引用类型在效率上是最佳的。
2.处理自赋值
在实现赋值运算符重载时,要考虑自赋值的问题,考虑一种情况,当构造函数中调用new在堆上开辟空间时,我们要考虑深拷贝的情况,
那么这种做法似乎是合理的。
Widget& Widget::operator=(const Widget &rhs) { delete pb; pb = new Bitmap(*rhs.pb); return *this; }
如果这时,该类的对象发生了自赋值,那么结果是致命的!delete掉了自身的Bitmap,使得自己的一个指针成员指向一个已经被删除的对象!!!