由于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
使用才会精进,一旦不使用,最简单的问题也会被遗忘
上一篇:M和N开头的食物英语单词
下一篇:开工动土吉祥祝福语