1. 程式人生 > >c++中淺復制與深復制

c++中淺復制與深復制

using 析構函數 但是 ret code 深拷貝和淺拷貝 pub set 期望

在C++中經常會遇到有關類對象的淺復制與深復制的問題,也是容易出錯的地方。

查找了相關資料,有關淺復制與深復制的定義為:對類進行復制的時候按位復制,即把一個對象各數據成員的值原樣復制到目標對象中。當類中涉及到指針類型數據成員的時候,往往就會產生指針懸掛問題。

class A{
public:
    int* a;
};
A a1;
A b1=a1;
b1=a1執行的是淺復制,此時a1.a和b1.a指向的是同一個內存地址,如果在析構函數裏面有對內存的釋放。就會出現內存訪問異常。因為一塊內存空間會被釋放兩次!
參考代碼理解:
#include <iostream>
#include 
<string.h> using namespace std; class person{ private: char *name; int age; public: person(const char *Name,int Age) { name=new char[strlen(Name)+1]; strcpy(name,Name); age=Age; cout<<"construct ..."<<endl; } ~person() { cout
<<"destruct ..."<<age<<endl; delete name; } void dispaly() { cout<<name<<" "<<age<<endl; } void setage(int x) { age=x; } }; int main() { person p1("jack",23); person p2=p1; p1.setage(10); // p2.setage(20);
p1.dispaly(); p2.dispaly(); return 0; }

技術分享

從運行結果我們可以看到程序只是調用了一次構造函數,但是卻執行了兩次析構函數,不符合預期期望。對象p2=p1執行的是淺復制,p2中指針name和p1中指針name是指向的同一地址,由於沒有定義構造函數,在執行p2=p1的時候,系統采用默認拷貝構造函數(默認的拷貝構造函數不會為新對象重新分配新的內存空間),即按位的拷貝方式將p1中各數據成員的值拷貝到p2的對應成員中,所以導致p1.name=p2.name(指向了同一內存),此時類person的構造函數只會執行一次。

當遇到main()函數最後的“}”的時候,執行析構函數,由析構函數執行的規律可知先構造的後執行,所以先執行p2的析構函數,此時系統將p2.name指向的存儲單元釋放,在執行p1析構函數的時候,p1.name所指向的內存單元又被釋放,這樣就會造成同一塊內存空間被釋放兩次,造成錯誤,p1.name也就成了懸掛指針。

  解決這一問題就需要對p1進行深拷貝,即構造拷貝函數,讓對象p2在拷貝p1的時候獲取新的內存空間。

#include <iostream>
#include <string.h>
using namespace std;

class person{
private:
    char *name;
    int age;
public:
    person(const char *Name,int Age)//構造函數
    {
        name=new char[strlen(Name)+1];
        strcpy(name,Name);
        age=Age;
        cout<<"construct ..."<<endl;
    }
    person(const person &p)//拷貝構造函數
    {
        name=new char[strlen(p.name)+1];
        strcpy(name,p.name);
        age=p.age;
        cout<<"copy construct ..."<<endl;
    }
    ~person()
    {
        cout<<"destruct ..."<<age<<endl;
        delete name;
    }
    void dispaly()
    {
        cout<<name<<" "<<age<<endl;
    }
    void setage(int x)
    {
        age=x;
    }
};
int main()
{
   person p1("jack",23);
   person p2=p1;
   p1.setage(10);
//   p2.setage(20);
   p1.dispaly();
   p2.dispaly();
    return 0;
}

技術分享

從運行結果可以看到符合預期期望,從拷貝構造函數定義可以知道,對類對象的復制,重新為新對象分配了新的內存單元。深拷貝和淺拷貝可以簡單理解為:如果一個類擁有資源,當這個類的對象發生復制過程的時候,資源重新分配,這個過程就是深拷貝,反之,沒有重新分配資源,就是淺拷貝。

定義拷貝構造函數的形式為:X(X& x){ a=new ??????}

什麽時候用到拷貝函數?

a.一個對象以值傳遞的方式傳入函數體;
b.一個對象以值傳遞的方式從函數返回; c.一個對象需要通過另外一個對象進行初始化。
 

c++中淺復制與深復制