形象地聊聊C++中的浅拷贝与深拷贝
来源:互联网 发布:淘宝买的假落红好用吗? 编辑:程序博客网 时间:2024/05/21 17:10
先来看一个简单的程序:
#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; // 1cout << B.y << endl; // 2return 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; // 0013FF7CPoint A(1, 2, &m);cout << A.x << endl; // 1cout << A.y << endl; // 2cout << A.pTest << endl; // 0013FF7CPoint B(A); // 执行了编译器默认的浅拷贝cout << B.x << endl; // 1cout << B.y << endl; // 2cout << B.pTest << endl; // 0013FF7Creturn 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; // 1cout << A.y << endl; // 2cout << A.pTest << endl; // 00032738cout << *A.pTest << endl; // 100Point B(A); // 执行了编译器默认的浅拷贝cout << B.x << endl; // 1cout << B.y << endl; // 2cout << B.pTest << endl; // 00032738cout << *B.pTest << endl; // 100return 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; // 1cout << A.y << endl; // 2cout << A.pTest << endl; // 00032738cout << *A.pTest << endl; // 100Point B(A); // 执行了编译器默认的浅拷贝cout << B.x << endl; // 1cout << B.y << endl; // 2cout << B.pTest << endl; // 00032738cout << *B.pTest << endl; // 100return 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; // 1cout << A.y << endl; // 2cout << A.pTest << endl; // 00032738cout << *A.pTest << endl; // 100Point B(A); // 执行了程序员自己写的深拷贝cout << B.x << endl; // 1cout << B.y << endl; // 2cout << B.pTest << endl; // 00030930cout << *B.pTest << endl; // 100return 0;}这就是深拷贝, 依靠程序员自己的实现, 撇清A对象和B对象的关系。
来个形象的总结吧:
浅拷贝: 丈夫有100元, 取了个没有钱的妻子后, 自己与妻子共同掌管这100元, 花着花着, 有可能吵架呢
深拷贝: 丈夫有100元, 取了个有100块钱的妻子后, 自己有100, 妻子有100, 各花各的, 互不干扰, 没有什么争吵
0 0
- 形象地聊聊C++中的浅拷贝与深拷贝
- C中的深拷贝和浅拷贝
- c++中的深拷贝与浅拷贝
- C#中的浅拷贝与深拷贝
- C#中的深拷贝与浅拷贝
- Python中的浅拷贝与深拷贝
- java中的深拷贝与浅拷贝
- IOS中的深拷贝与浅拷贝
- python中的深拷贝与浅拷贝
- Java中的浅拷贝与深拷贝
- c++中的浅拷贝与深拷贝
- java 中的深拷贝与浅拷贝
- C++中的深拷贝与浅拷贝
- Javascript中的深拷贝与浅拷贝
- java中的深拷贝与浅拷贝
- Java中的深拷贝与浅拷贝
- Java中的浅拷贝与深拷贝
- iOS中的深拷贝与浅拷贝
- poj 3067
- php的页面静态化技术 ob(out_put buffering)
- awk的类sql数据处理
- C语言实现strlen()4种方法和strcat()3种方法
- VI VIM相关命令
- 形象地聊聊C++中的浅拷贝与深拷贝
- JS代码屏蔽鼠标右键点击
- 开源机器人控制平台linuxcnc
- (五)storm-kafka源码走读之KafkaSpout
- 好长时间没有上了!
- MySQL 的 ON DUPLICATE KEY UPDATE
- 线程中锁的运用及遇到的问题
- 【leetcode 链表】 Merge Two Sorted Lists 和 Merge k Sorted Lists
- 面向对象——比抽象类更抽象的