如何理解深拷貝和淺拷貝

首先我們先記住一個結論:編譯器自動生成的拷貝構造和賦值運算符是memcpy的一個過程。

實例過程以結構體代替,在c++中struct和class除了默認訪問權限基本等同。 


struct TestStruct1
{
    int arr[3];
    int a;
};

int main()
{
   TestStruct1 oneVar;
   oneVar.arr[0]=1;
   oneVar.arr[1]=2;
   oneVar.arr[2]=3;
   oneVar.a=4;

   TestStruct1 twoVar=oneVar;
}

 拷貝構造直接將oneVar的內存空間拷貝到twoVar的內存空間中。

 考慮一個成員指針的情況:

struct TestStruct2
{
	int arr[3];
	int *a;
};

int main()
{
    TestStruct1 oneVar;
	oneVar.arr[0] = 1;
	oneVar.arr[1] = 2;
	oneVar.arr[2] = 3;
	oneVar.a = new int(4);

	TestStruct1 twoVar = oneVar;
}

 由此看出oneVar和twoVar的指針成員共享了oneVar.a的堆內存空間,如果oneVar和twoVar其中一個執行了delete oneVar.a或者

delete twoVar.a(4這塊內存被回收了),這個時候另外一個變量再次從a取值就是產生未定義的行爲。

爲了解決上述共享堆內存而引發的未定義行爲問題,引入了深拷貝

struct TestStruct3
{
	int arr[3];
	int *a;
    
    TestStruct3(){}

    TestStruct3(const TestStruct3& other)
    {
        this->arr[0]=other.arr[0];
        this->arr[1]=other.arr[1];
        this->arr[2]=other.arr[2];
        this->a = new int(*(other.a)); // 深拷貝解決的問題
    }
	~TestStruct3()
	{
		delete a; // 顯式釋放堆內存,否則默認的析構函數不會釋放對內存
		a = nullptr;
	}
};

int main()
{
    TestStruct3 oneVar;
    oneVar.arr[0]=1;
    oneVar.arr[1]=2;
    oneVar.arr[2]=3;
    oneVar.a = new int(4);

    TestStruct3 twoVar = oneVar;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章