拷贝构造函数与重载赋值运算符
拷贝构造函数
如果一个构造函数的第一个参数是自身类类型的引用,且任何额外的参数都有默认值,则此构造函数是拷贝构造函数。(C++ premier里的定义)
拷贝构造函数应用的场景:
- 用一个对象初始化另外一个对象
- 函数的参数是一个对象,并且是值传递方式
- 函数的返回值是一个对象,并且是值传递方式
特别注意的是定义一个类时,编译器会给我们定义一个默认拷贝构造函数(点击查看默认成员函数)
默认拷贝构造函数
class CTest { public: int i; CTest(){cout << "construct" << endl;} ~CTest(){cout << "discontruct" << endl;} }; void test(CTest obj) { } int main() { CTest testObj; test(testObj); return 0; }
这个程序运行的结果为:
construct discontruct discontruct
当 testObj 以值传递的方式传入test函数时,此时会生成一个CTest类型的临时变量,但是此时编译器采用的是位拷贝(按字节复制)的方式,调用默认拷贝构造函数,并不调用 CTest类的构造函数。
对于类中普通的成员变量,如int, double, char等,c++提供默认的拷贝构造函数,我们可以不用写拷贝构造函数。
如果类中成员有*指针(深拷贝,浅拷贝问题),那么我们就需要写自己的拷贝构造函数。
例
若此时定义对象CExample obj1;并且obj1有指向动态分配的内存obj1.Init(40)。
现在用obj1来初始化obj2,CExample obj2=obj1,则此时调用的是默认拷贝构造函数,复制所有成员的值,所以obj1.pBuffer=obj2.pBuffer,两个对象里的指针指向了同一块内存。
如果obj1修改pBuffer指向内存里的数据,则obj2访问pBuffer指向的数据也会发生变化,这显然不是我们想要的结果。(需要让它们互不干扰)
所以我们要自己写拷贝构造函数(不是复制指针,而是复制指针指向的动态内存里的内容)。如下图:
重载赋值运算符“=”
CTest test1; CTest test2 = test1; CTest test2 (test1);
此时调用test1的拷贝构造函数初始化对象test2
但是对于下面的表达式:调用的是重载的赋值运算符
CTest test1,test2; test2 = test1;
拷贝构造函数和赋值的区别
- 用一个已存在的对象去构造一个不存在的对象(构造之前不存在),就是拷贝构造.
- 用一个已存在的对象去覆盖另一个已存在的对象,就是赋值运算.
- 拷贝构造函数从一个已经存在的变量来初始化一个新声明的变量,不需要清除现有的值(因为是新创建,所以没有现有值)
- 拷贝构造函数没有返回值。
- 赋值运算符return *this.(This is necessary to allow multiple assignment, eg x = y = z;)
同样,编译器为我们的类提供默认的赋值符“=”
默认”=“的恶果
- 默认的“=”只是将成员变量的值相应复制。
- 旧指针的值被丢弃了,但指针指向的内容并未释放 。
- 新指针的值被复制了,但指针所指内容并未复制 。
所以当有动态分配的内存时,要重载赋值运算符
总结
- 注意默认的拷贝构造函数和”=“的作用。
- 拷贝构造函数和赋值符的区别。
- 应该为所有包含动态分配成员的类都提供拷贝构造函数。
- 有时需要重载赋值运算符。
感谢
- 李昕老师(CUMT)
- 20170825_string构造函数、析构函数、拷贝构造函数以及重载赋值运算符
- 如何禁用拷贝构造函数和禁用重载赋值运算符
- c/c++ 构造函数、拷贝构造函数、析构函数和赋值运算符重载
- 类的赋值运算符重载和拷贝构造函数
- C++ 一个demo看懂—拷贝构造函数与赋值运算符重载区别
- 拷贝构造函数和赋值运算符的重载的调用次数问题
- 重载赋值运算符与拷贝构造函数的区别
- 1、C++关于拷贝构造函数和赋值运算符重载问题的测试程序。因为调用顺序不清,导致内存泄漏new delete
- c++拷贝构造函数、赋值运算符=重载、深拷贝与浅拷贝
- [ZZ]重载赋值运算符与拷贝构造函数的区别
- [C++基础]046_拷贝构造函数与重载赋值运算符(精深版解释)
- C++构造函数、拷贝构造函数、赋值运算符重载 调用时机 GCC与VC在对象作为返回值的不同处理
- 关于拷贝构造函数和赋值运算符
- 拷贝构造函数,赋值运算符重载,友元输出重载
- 拷贝构造函数和赋值运算符 区别
- 拷贝构造函数与赋值运算符的认识
- 【面试题一】类型转换关键字,空类对象模型,拷贝构造函数,赋值运算符函数
- 重载赋值运算符
- 【面试题001】类型转换关键字,空类对象模型,拷贝构造函数,赋值运算符函数
- 赋值运算符和拷贝构造函数