1 class A
2 {
3 public:
4 A(int x) : _x(x){}
5 ~A(){}
6 public:
7 int _x; //方便测试改为public
8 public:
9 A(const A& a){_x = a._x;}
10 A &operator=(const A& a);
11 };
12
13 A &A::operator=(const A &a)
14 {
15 if(this == &a) return *this;
16
17 _x = a._x;
18
19 return *this;
20 }
先看上面一段简单代码,写的很简单的浅拷贝,之前对于复制构造函数存在相当多的不理解。
(1)不理解为什么参数要写成引用,后来看了剑指offer后,上面说如果不写成引用,调用A的复制构造函数时参数会copy,此时会调用自己本身的复制构造函数,所以一层层的调用,直到栈溢出。
(2)赋值运算符函数为什么要返回实例自身的引用,主要是为了支持如下功能:
A a(10);
A b(20);
A c(30);
a = b = c;
如果返回的是void,就无法支持a = b = c,至于为什么返回的是引用,请看下面的式子:
如果赋值运算符函数为这样: A operator=(const A& a);
(a = b) = c;
结果a._x 等于多少? 结果是20,而不是30,因为返回的不是引用,只是一个临时的对象,修改的也是那个临时对象的值,而不是对象a的 值。
(3)赋值运算符函数内部为什么是const 并且是引用,因为赋值运算符函数不会改变传入实例的状态,因此需要加上const,至于为什么是引用,则是因为如果不是引用,参数会被复制一份副本,从而会调用一次复制构造函数,会增加函数调用的开销。