拷贝构造函数
深拷贝和浅拷贝
所谓“深拷贝”和“浅拷贝”,各自代表不同的意义,各有所需。主要要分清值语意和引用语意。
值语意:x=y完成复制后,得到的x完全独立于y, x的改变不会影响原来的y。
引用语意:x=y完成复制后,修改x会影响y,x,y某种程度上共享了一片内存空间,存在耦合的。如下:
class OBJ{ public: int a; char *b; };
所以拷贝,其实都是值传递,只是C++中一个对象包含指针时候,直接浅拷贝会把指针的值传递给另一个对象,也就是这两个对象的中的指针成员指向了同一片存储空间。 所以深拷贝和浅拷贝的区别只存在于类中包含指针变量的时候。下面这个类是不存在深拷贝浅拷贝的,都是值语意。
class OBJ{ public: int a; char b; };
为什么拷贝构造函数的如参最好是const的引用?
C++ primer中说到拷贝构造函数时,建议入参都写成const的引用,即
A(const A &other)
而不是:
A(A &other)
原因是什么?以下是我写一个BigInt类遇到的问题:
a,b都是BigInt类型,我重载了加法运算,得到的依然是一个BigInt,我以为BigInt sum = a + b会调用构造函数BigINt(BigInt &bi),但是a+b得到的是一个右值(函数的返回值是右值),而BigINt(BigInt &bi)需要一个左值左入参。所以编译的时候报错,提示找不到匹配的构造函。
要弄清这个报错,首先要搞懂左值和右值的概念。
左值的定义就是非临时变量,可以在多个语句中使用。右值的定义就是临时对象,只在当前语句中有效。
我简单的认为,左值是存放在内存地址上的,可以寻址,所以可以反复使用。右值不能寻址,存放在代码片段上。
在 C++11 之前,右值是不能被引用的,我写的代码企图引用右值,所以这里报错。改成BigInt(const BigInt &bi)就正确了。
思考:拷贝构造函数入参一定都是const么?
答:不是。比如智能指针Shared_ptr的copy constructor,此时的入参是会发生变化的,因为其引用计数器发生了变化,要做++操作。