C++运算符重载(3) - 什么时候需要自定义赋值操作符

来源:互联网 发布:淘宝宝贝介绍图片尺寸 编辑:程序博客网 时间:2024/06/05 18:37
答案与拷贝构造函数一样。如果一个类不包含指针,则不需要自定义赋值操作符与拷贝构造函数。编译器会给每个类创建一个默认的拷贝构造函数和默认的赋值操作符。但是,当类中包含有指针或任何运行时分配的资源时,编译器生成的这两个函数,可能会失效。
参考下面程序:
#include<iostream>using namespace std; // 没有自定义赋值操作符class Test{    int *ptr;public:    Test (int i = 0)        { ptr = new int(i); }    void setValue (int i) { *ptr = i; }    void print()             { cout << *ptr << endl; }}; int main(){    Test t1(5);    Test t2;    t2 = t1;    t1.setValue(10);    t2.print();    return 0;}
上面程序输出结果为: 10

仔细看下main函数,会发现使用setValue()修改了t1的值后,对象t2也跟着改变了。这会导致未知的行为。
因为上面程序没有自定义赋值操作符,所以编译器生成了一个默认的,会将'ptr‘从右侧拷贝到左侧。所以两个对象中的ptr指向相同位置。

可以使用两种方法来解决上面问题:
1) 禁止对象之间进行赋值操作。我们可以使用自定义的赋值运算符并定义为private.
2) 自定义赋值运算符来实现深拷贝(deep copy).
对于拷贝构造函数,也是同样的道理。

下面是重载了赋值运算符后的程序:

#include<iostream>using namespace std; class Test{    int *ptr;public:    Test (int i = 0)      { ptr = new int(i); }    void setValue (int i) { *ptr = i; }    void print()          { cout << *ptr << endl; }    Test & operator = (const Test &t);}; Test & Test::operator = (const Test &t){   //检测是否为自己   if(this != &t)     *ptr = *(t.ptr);    return *this;}int main(){    Test t1(5);    Test t2;    t2 = t1;    t1.setValue(10);    t2.print();    return 0;}
运行结果:
5

我们应该同时给上面程序加入拷贝构造函数,运行类似这样的语句时“Test t3 = t4;” 不会出现未知行为。

注意赋值操作符中的if条件判断。当重载赋值操作符时,必须要检查自我赋值。否则,一个对象赋值给它自己,可能会导致未知的行为。在上面程序中,不一定需要自我赋值检查,因为ptr总是指向一个整数,可以重用相同内存。但是总体来说,检查自我赋值是一个好的编程实践方法。

0 0
原创粉丝点击