浅拷贝与深拷贝

浅拷贝

#include "stdafx.h"
#include 

class CTest
{
public:
    CTest();
    ~CTest();

private:
    int m_nNum;
    char *m_pName;
};

CTest::CTest()
{
    m_pName = new char[20];
    std::cout << "Construct Funcation" << std::endl;
}

CTest::~CTest()
{
    if (nullptr != m_pName)
    {
        delete m_pName;
        m_pName = nullptr;
    }

    std::cout << "Destruct Funcation" << std::endl;
}

int main()
{
    /*为了方便观察 放进局部里*/
    {
        CTest Test1;
        CTest Test2 = Test1;
    }

    system("pause");
    return 0;
}
浅拷贝与深拷贝_第1张图片
image.png
  • 直接运行上面的代码的话 会出现上面的错误


    浅拷贝与深拷贝_第2张图片
    image.png

    浅拷贝与深拷贝_第3张图片
    image.png
  • 通过打印结果和调用堆栈可以发现 析构函数被调用了两次 而构造函数只调用了一次!

  • 那么可以猜想 在对Test2 进行赋值的时候并没有调用构造函数 并且Test2和Test1是同一个地址

  • 虽然这里对pName进行了置nullptr 但是别忘了 新进去的时候 pName还时原来的状态...(想想C的栈结构 改的是栈里的 和原来的值没有关系) 所以这里设置nullptr依然是无法防止多次析构的

  • 这里可以发现拷贝的数据仅仅是指针拷贝了而已 指向了同一块区域 并没有开新的内存 浅拷贝只进行了指针的复制


深拷贝

#include "stdafx.h"
#include 

class CTest
{
public:
    CTest(char *pName, int nNum = 1);
    CTest(CTest& obj);
    ~CTest();
    CTest& operator = (CTest& obj);
private:
    int m_nNum;
    char *m_pName; 
};

CTest::CTest(CTest& obj)
{
    m_nNum = obj.m_nNum;

    m_pName = new char[strlen(obj.m_pName) + 1];
    strcpy_s(m_pName, strlen(obj.m_pName) + 1, obj.m_pName);

    std::cout << "Construct Funcation obj" << std::endl;
}

CTest::CTest(char *pName, int nNum) : m_nNum(nNum)
{
    m_pName = new char[strlen(pName) + 1];
    strcpy_s(m_pName, strlen(pName) + 1, pName);
    std::cout << "Construct Funcation" << std::endl;
}


CTest::~CTest()
{
    if (nullptr != m_pName)
    {
        delete m_pName;
        m_pName = nullptr;
    }

    std::cout << "Destruct Funcation" << std::endl;
}

/*重载运算符*/
CTest & CTest::operator=(CTest & obj)
{
    std::cout << "Operator overloading" << std::endl;
    if (m_pName == obj.m_pName)
    {
        return *this;
    }

    if (m_pName != nullptr)
    {
        delete[] m_pName;
        m_pName = nullptr;
    }

    m_nNum = obj.m_nNum;

    m_pName = new char[strlen(obj.m_pName) + 1];
    strcpy_s(m_pName, strlen(obj.m_pName) + 1, obj.m_pName);
    // TODO: 在此处插入 return 语句
    return *this;
}

int main()
{
    char szName[8] = "xiao";
    /*为了方便观察 放进局部里*/
    {
        CTest Test1(szName);
        CTest Test2 = Test1;
    }

    system("pause");
    return 0;
}
浅拷贝与深拷贝_第4张图片
image.png
  • 改造原来的函数 重载构造函数
  • 因为是单参 = 与 ()的写法相同
重载为新开堆 这样进行构造时 进入重载函数
因为新开了堆 所以释放时是各自释放各自的堆
这样就避免了浅拷贝重复释放同一区域的问题
但是 会多使用内存空间

运算符重载

浅拷贝与深拷贝_第5张图片
image.png
如果用运算符重载来做 那么会进行两次构造 一次运算符重载 两次析构 

你可能感兴趣的:(浅拷贝与深拷贝)