文章开始给大家瞧瞧昨晚拍的大黄
嘿嘿~
捞捞之前的总结:十万字带你学习C++(细节拉满)
什么是浅拷贝?
在未定义显示拷贝构造函数的情况下,系统会调用默认的拷贝函数——即浅拷贝,它能够完成成员的一一复制,按位拷贝。
即浅拷贝:简单的赋值拷贝操作(这个是系统默认提供的)
如下所示:我没有写显式写出拷贝构造函数和拷贝赋值函数,编译器会给我们默认提供拷贝构造和拷贝赋值函数
当我们给出上述代码显示的浅拷贝构造时:
INT(const INT &my):value(my.value),ladder(my.ladder)//用初始化列表初始化的
{
cout << "拷贝构造函数 " << this << endl;
}
看到这里我们会明白当使用对象初始化对象时,系统会默认的给出拷贝构造函数(俗称浅拷贝)进行初始化,让我们看下述代码,思考一下为什么会报错呢?
class MyString
{
private:
char* str;
public:
MyString(const char* p = nullptr) :str(nullptr)
{
if (p != nullptr)
{
int n = strlen(p) + 1;
str = new char[n];
strcpy_s(str, n, p);
}
else
{
str = new char[1];
*str = '\0';
}
cout << "构造函数调用" << this << endl;
}
MyString(const MyString& m) :str(m.str)//浅拷贝
{
cout << "浅拷贝调用" << this << endl;
}
~MyString()
{
delete[]str;
str = nullptr;
cout << "析构调用" << this << endl;
}
void Print()
{
cout << "内容是: " << str << endl;
}
};
int main()
{
MyString h1("i love you");
MyString h2(h1);
h1.Print();
h2.Print();
return 0;
}
原因是:当数据成员中有指针时,如果采用简单的浅拷贝,则两类中的两个指针将指向同一个地址,当对象快结束时,会调用两次析构函数,同一块空间会被释放两次,而导致指针悬挂现象
上述代码在内存的分布如下:
在我们编写有的代码时,不可能数据成员不会存在指针,或者过程中不进行动态分配内存的操作,那么如何解决问题这就引出了下面什么是深拷贝的问题。
什么是深拷贝?
当类持有其它资源时,例如动态分配的内存、指向其他数据的指针等,默认的拷贝构造函数就不能拷贝这些资源了,我们必须显式地定义拷贝构造函数,以完整地拷贝对象的所有数据。这就是深拷贝。
- 深拷贝与浅拷贝的区别就在于深拷贝会在堆内存中另外申请空间来储存数据,从而也就解决了指针悬挂的问题。简而言之,当数据成员中有指针时,必须要用深拷贝。
对于上述问题代码,具体做法便是重新开辟一个内存空间存放数据,利用深拷贝构造函数使h2的指针指向新开辟的空间,这样,h1与h2各指向一块堆区的数据,两块空间存放的数据是一样的,这样就在拷贝的同时避免了对同一空间的重复释放问题。
将上述浅拷贝更改为深拷贝:
MyString(const MyString& m) //深拷贝
{
int n = strlen(m.str) + 1;
str = new char[n];
strcpy_s(str, n, m.str);
cout << "深拷贝调用" << this << endl;
}
总结:
C++默认生成的拷贝构造函数他的行为是浅拷贝,他只会复制一个一模一样的指针,并不会操作指针指向的东西,想要实现我们的逻辑需求,就需要自定义拷贝构造函数,实现深拷贝。
最后的最后让我再用大白话对于深浅拷贝做一个描述,希望看过之后能对其有着深刻的理解
- 当我们有一个房子类时,我们向C++开发商购买了一套房子(声明了一个房子对象),初始化时拿到了房子的钥匙,此时有一个人也向C++购买了一套房子,C++开发商通过对象初始化对象的方法,让另一个拿到了他房子的钥匙,当他去住房时突然发现,诶?怎么房子有人住了(也就是我),这就相当于我和他共住了同一套房子(地址相同),我和他的钥匙都指向这一套房子,当我们办理拆迁时(调用析构函数时),一个房子总不可能拆迁两次吧,这就出现了问题。这就是浅拷贝,只复制指向某个对象的指针,而不复制对象本身,新旧对象还是共享同一块内存。
- 当我购买了一个130平的房子时,此时另一个人也来买房,C++开发商通过对象初始化对象的方法,根据我买的130平大小的房子,给另一个人也找了套同样大小的房子,配了钥匙,此时我和他就是各自住一套房子,房子地址不同,当办理拆迁时,互不影响,你拿你的拆迁费,我拿我的。这就是深拷贝,是开辟一块新的内存地址,将原对象的各个属性逐个复制进去,新对象跟原对象不共享内存,对拷贝对象和源对象各自的操作互不影响。
点赞收藏是对博主最大的鼓励!感谢!