首页 > 代码库 > Cpp下的深拷贝与浅拷贝探究

Cpp下的深拷贝与浅拷贝探究

 

下面,通过代码来说说C++中的深浅拷贝

#define   _CRT_SECURE_NO_WARNINGS#include<iostream>using namespace std;class Name{public:    Name(const char*myp){        m_len = strlen(myp);        mp = (char*)malloc(m_len + 1);        strcpy(mp, myp);    }    ~Name(){        if (mp != NULL)        {            free(mp);            mp = NULL;            m_len = 0;        }    }private:    char *mp;    int m_len;};void playmain(){    Name obj1("abcdef");    Name obj2 = obj1;  // 执行默认拷贝构造函数}int main(){    playmain();    cout <<"hello world"<<endl;    system("pause");    return 0;}

我们通过断点,一步一步地调试程序:

技术分享

继续往下走:

技术分享

继续往下走:

技术分享

由于我们并没有重写自己的拷贝构造函数,因此执行的是默认的拷贝构造函数。当Name obj2=obj1执行完毕后,也就是函数playmain()执行完毕了,开始调用对象的析构函数:

技术分享

首先析构的是obj2,当其析构完毕后,程序返回:

技术分享

我们接着往下走:

技术分享

继续F11往下走,我们会发现程序崩溃了:

技术分享

下面,我们来分析一下,为什么程序会崩溃在这里?原因很简单,因为我们重写自己的拷贝构造函数,而使用了默认的拷贝构造函数,也就是C++编译器为我们进行了一次浅拷贝。那么何为浅拷贝呢?下面来看张图:

技术分享

也就是说,当我们第一次析构对象obj2的时候,已经将内存空间0x1111释放了,而obj1和obj2都指向了同一块内存空间,当obj1执行析构函数的时候,它所指向的内存空间已经被释放,再次进程释放,肯定程序会崩溃。到此 ,我们清楚知道,导致程序崩溃的原因是C++编译器仅仅执行了浅拷贝,而浅拷贝的根源在于我们没有重写自己的拷贝构造函数,所以解决办法,当然是重写自己的拷贝构造函数,从而实现深拷贝-------将对象完完全全的赋值一份(包括指针指向的内存空间也复制一份)

技术分享

再次执行程序,不会出现崩溃现象。上述对应的内存四区模型如下:

技术分享

 同理,如下代码中也会出现程序崩溃,也需要我们显式重载"="运算符

技术分享

没有重载=运算符内存四区模型如下:

初始条件:

技术分享


执行等号操作后:

技术分享

解决方案:手动重载=运算符

 

Cpp下的深拷贝与浅拷贝探究