先来看一个简单的程序:
#include <iostream> using namespace std; class Point { public: int x; int y; Point(int xx, int yy) { x = xx; y = yy; } }; int main() { Point A(1, 2); Point B(A); // 执行了编译器默认的浅拷贝 cout << B.x << endl; // 1 cout << B.y << endl; // 2 return 0; }
好, 继续看:
#include <iostream> using namespace std; class Point { public: int x; int y; int* pTest; Point(int xx, int yy, int* p) { x = xx; y = yy; pTest = p; } }; int main() { int m = 0; cout << &m << endl; // 0013FF7C Point A(1, 2, &m); cout << A.x << endl; // 1 cout << A.y << endl; // 2 cout << A.pTest << endl; // 0013FF7C Point B(A); // 执行了编译器默认的浅拷贝 cout << B.x << endl; // 1 cout << B.y << endl; // 2 cout << B.pTest << endl; // 0013FF7C return 0; }由此可见, 浅拷贝就是浅浅的傻傻的拷贝。 上面这个程序会引出一个问题: 如果A.pTest指向了某一个堆, 那么B.pTest也指向了同一地方。 我们来看看:
#include <iostream> using namespace std; class Point { public: int x; int y; int* pTest; Point(int xx, int yy) { x = xx; y = yy; pTest = new int(100); } }; int main() { Point A(1, 2); cout << A.x << endl; // 1 cout << A.y << endl; // 2 cout << A.pTest << endl; // 00032738 cout << *A.pTest << endl; // 100 Point B(A); // 执行了编译器默认的浅拷贝 cout << B.x << endl; // 1 cout << B.y << endl; // 2 cout << B.pTest << endl; // 00032738 cout << *B.pTest << endl; // 100 return 0; }显然, 如果析构, 则会有两次释放同一堆空间, 危险!!!看看这个危险的代码:
#include <iostream> using namespace std; class Point { public: int x; int y; int* pTest; Point(int xx, int yy) { x = xx; y = yy; pTest = new int(100); } ~Point() { delete pTest; } }; int main() { // 代码两次释放同一堆空间, 运行的时候出错 Point A(1, 2); cout << A.x << endl; // 1 cout << A.y << endl; // 2 cout << A.pTest << endl; // 00032738 cout << *A.pTest << endl; // 100 Point B(A); // 执行了编译器默认的浅拷贝 cout << B.x << endl; // 1 cout << B.y << endl; // 2 cout << B.pTest << endl; // 00032738 cout << *B.pTest << endl; // 100 return 0; }上面的代码不仅错误, 而且从逻辑上吧对象A和B无形地建立了关联, 显然是不合理的。
看来, 编译器默认的拷贝构造函数是太肤浅了, 编译器不可能做那么多东西, 从逻辑上来讲,也无法做。 是该搞点深的了, 来看程序员自己需要写的深拷贝:
#include <iostream> using namespace std; class Point { public: int x; int y; int* pTest; Point(int xx, int yy) { x = xx; y = yy; pTest = new int(100); } ~Point() { delete pTest; } Point(Point& P) // 不能是Point(Point P) { x = P.x; y = P.y; int value = *P.pTest; pTest = new int(value); } }; int main() { Point A(1, 2); cout << A.x << endl; // 1 cout << A.y << endl; // 2 cout << A.pTest << endl; // 00032738 cout << *A.pTest << endl; // 100 Point B(A); // 执行了程序员自己写的深拷贝 cout << B.x << endl; // 1 cout << B.y << endl; // 2 cout << B.pTest << endl; // 00030930 cout << *B.pTest << endl; // 100 return 0; }这就是深拷贝, 依靠程序员自己的实现, 撇清A对象和B对象的关系。
来个形象的总结吧:
浅拷贝: 丈夫有100元, 取了个没有钱的妻子后, 自己与妻子共同掌管这100元, 花着花着, 有可能吵架呢
深拷贝: 丈夫有100元, 取了个有100块钱的妻子后, 自己有100, 妻子有100, 各花各的, 互不干扰, 没有什么争吵