[C++] 浅拷贝和深拷贝
浅拷贝只是简单的值拷贝;
深拷贝需要重新分配空间。
系统默认的拷贝构造函数属于浅拷贝。
#include <iostream> using namespace std; class A { public: char *p; A(char *a) { int len = strlen(a) + 1; p = new char[len]; memcpy(p, a, len); } void print(void) { cout << p << endl; } }; int main(void) { A m("Hello"); m.print(); // 使用系统默认的拷贝构造函数 A n(m); n.print(); // 修改对象m的成员变量,对象n的也随之改变 strcpy(m.p, "World"); m.print(); n.print(); }
输出结果为:
Hello
Hello
World
World
为什么修改对象 m 的值,对象 n 的值也随之改变?
原因是在创建对象 m 时,构造函数中为其分配了所需要的内存空间,对象 m 的成员变量指针 p 会指向分配内存空间的首地址;
当使用默认的拷贝构造函数,利用对象 m 初始化对象 n 时,只是简单的将对象 n 的成员变量指针 p 也指向对象 m 分配的内存空间的首地址;
两个指针指向同一个内存空间,当其中任意一个对象修改了内存空间中的值,另一个也随之改变。
浅拷贝的影响:
如果在类的析构函数中 delete 内存,那么同一块内存会被销毁两次,这样会导致系统错误。
如果想要在修改其中一个对象时而不影响另一个对象,就要使用深拷贝,也就是自定义拷贝构造函数,在拷贝构造函数中为新对象重新分配内存空间。
#include <iostream> using namespace std; class A { public: char *p; A(char *a) { int len = strlen(a) + 1; p = new char[len]; memcpy(p, a, len); } // 自定义拷贝构造函数,深拷贝 A(const A &a) { int len = strlen(a.p) + 1; // 重新分配内存空间 p = new char[len]; memcpy(p, a.p, len); } void print(void) { cout << p << endl; } }; int main(void) { A m("Hello"); m.print(); // 使用自定义的拷贝构造函数 A n(m); n.print(); // 修改对象m的成员变量,对象n的不会改变 strcpy(m.p, "World"); m.print(); n.print(); }
输出结果为:
Hello
Hello
World
Hello