由于20年转行之后一直用的是halcon 和c# ,C++就此搁浅,最近开始搞pcl慢慢的又重拾起来,对于深拷贝和浅拷贝我知道是什么原因造成的,也知道如何解决,但是突然被人问得时候又有点蒙蔽,因此做一个简单的总结。
先看浅拷贝和深拷贝的区别:
浅拷贝:只复制指向某个对象的指针,而不复制对象本身,新旧对象还是共享同一块内存,进行简单的赋值拷贝运算,地址是一样的
深拷贝:new 出来的,在堆区申请了内存空间,
先举一个例子:作为一个足球迷,真心希望梅西能2022 拿下世界杯,对我们这些没有天赋的普通人来说,天赋比努力要重要100000倍(当你真正的努力过你就知道天赋有多么重要)。
- class WorldCupChampion
- {
- public:
- string country;
- int* years;
- WorldCupChampion();
- WorldCupChampion(std::string country, int years);
- ~WorldCupChampion();
- };
- WorldCupChampion::WorldCupChampion()
- {
- cout << "默认构造" << endl;
- }
-
-
- WorldCupChampion::WorldCupChampion(string country, int years)
- {
-
- this->country = country;
- this->years = new int(years);
- cout << "调用有参构造 " << *(this->years) << " " << this->country << endl;
- }
- WorldCupChampion::~WorldCupChampion()
- {
- cout << "调用析构函数 " << endl;
- if (years != NULL) // 由于year是new 在堆区的所以我们要在程序结束的时候将其delete掉
- {
- delete years;
- years = NULL;
- }
-
- }
然后我们在复制一个放到b 里面
- void test()
- {
- WorldCupChampion a("阿根廷", 2022);
- cout << *(a.years) << "世界杯冠军是 : " << a.country << endl;
-
- WorldCupChampion b(a);
- cout << *(b.years) << "世界杯冠军是 : " << b.country << endl;
-
- }
此时我们进行编译:ok
运行:
我们采用断掉调试,毕竟一切皆地址:

分析一下:我们在 创建一个对象a,然后赋值b ,将a 的所有的东西都复制给b ,但是,包括new 出来的东西,从上面的测试可以看出,我们现在的拷贝years 的地址是一样的,也就是说a 和b 的指针都指向了同一块内存空间。

那么当程序退出的时候我们要析构掉,当a 析构的时候已经将2022 这块内存空间已经析构了,那么当b 再次析构的时候 已经没有这块
内存了,导致程序报错。
浅拷贝带来的问题得本质是析构函数多长释放堆空间
为了解决上面的问题:我们自定义了一个拷贝---深拷贝
模式如下:
WorldCupChampion(const WorldCupChampion& a);
我们需要在这个构造当中重复new 出一片空间来存储year
- WorldCupChampion::WorldCupChampion(string country, int years)
- {
-
- this->country = country;
- this->years = new int(years);
- cout << "调用有参构造 " << *(this->years) << " " << this->country << endl;
- }
下面我们先看结果:

OK,那我们再次使用断点来看看这次他两的地址是不是一样的:


完整代码:
- #if 1
- class WorldCupChampion
- {
- public:
- string country;
- int* years;
- WorldCupChampion();
- WorldCupChampion(std::string country, int years);
- WorldCupChampion(const WorldCupChampion& a);
- ~WorldCupChampion();
- };
- WorldCupChampion::WorldCupChampion()
- {
- cout << "默认构造" << endl;
- }
-
- WorldCupChampion::WorldCupChampion(const WorldCupChampion& a)
- {
- cout << "深度拷贝" << endl;
- this->country = a.country;
- this->years = new int(*a.years);
- }
- WorldCupChampion::WorldCupChampion(string country, int years)
- {
-
- this->country = country;
- this->years = new int(years);
- cout << "调用有参构造 " << *(this->years) << " " << this->country << endl;
- }
- WorldCupChampion::~WorldCupChampion()
- {
- cout << "调用析构函数 " << endl;
- if (years != NULL) // 由于year是new 在堆区的所以我们要在程序结束的时候将其delete掉
- {
- delete years;
- years = NULL;
- }
-
- }
- void test()
- {
- WorldCupChampion a("阿根廷", 2022);
- cout << *(a.years) << "世界杯冠军是 : " << a.country << endl;
-
- WorldCupChampion b(a);
- cout << *(b.years) << "世界杯冠军是 : " << b.country << endl;
-
- }
- int main()
- {
- test();
- return 0;
- }
- #endif
使用才会精进,一旦不使用,最简单的问题也会被遗忘