深拷貝與淺拷貝

一、淺拷貝和深拷貝

   所謂淺拷貝,就是由默認的拷貝構造函數所實現的對數據成員逐一賦值。若類中含有指針類型的數據,這種方式只是簡單的把指針的指向賦值給新成員,但並沒有給新成員分配內存,因此這種方式必然會導致錯誤。爲了解決淺拷貝出現的錯誤,必須顯示的定義一個拷貝構造函數,使之不但複製數據成員,而且爲對象分配各自的內存空間,這就是所謂的深拷貝。


二、淺拷貝

   淺拷貝就是由默認的拷貝構造函數所實現的數據成員逐一賦值。通常默認的拷貝構造函數能夠勝任這個工作,但是若類中含有指針類型的數據,這種數據成員逐一賦值的方式將會產生錯誤。

例:

class Student
{
public:
                Student( char *name ,int age)         //構造函數
                {
                                _name = new char [10];           //分配內存
                                strcpy(_name, name);
                                _age = age;
                }
                ~Student()
                {
                                 delete[] _name;                 //釋放動態內存
                }
                 void display()
                {
                                cout << _name << "--" << _age << endl;
                }
private:
                 char *_name;
                 int _age;
};

int main()
{
                 Student st1("lisi" , 20);
                 Student st2(st1);               //調用默認的拷貝構造函數創建一個新的對象
                system( "pause");
                 return 0;
}




    程序運行,創建st1時調用構造函數 ,用運算符new從堆上分配一塊空間,並用_name指向這塊內存空間。在執行st2語句時,因爲沒有定義拷貝構造函數,所以調用默認的拷貝構造函數:

                Student(Student&st)

                {

                                _name =st._name;                  //並沒有爲對象st2的數據成員_name分配新的內存空間

                                _age =st._age;

                }


    主程序結束時,對象被逐個撤銷,先撤銷對象st2(因爲st2後創建),撤銷前先調用析構函數,用delete運算符釋放所分配的內存空間;撤銷對象st1時,第二次調用析構函數,因爲這時_name所指向的內存空間已經被釋放,企圖對同一塊內存空間釋放兩此,所以這時候程序出錯。

執行過程如圖:


spacer.gif

三、深拷貝

 爲了解決淺拷貝出現的錯誤,必須顯示的定義一個拷貝構造函數,使之不但能複製數據成員,而且爲指針分配各自的動態內存。

例:

class Student
{
public:
                Student( char *name ,int age)         //構造函數
                {
                                _name = new char [10];           //分配內存
                                strcpy(_name, name);
                                _age = age;
                }
                Student( Student& st )                 //自定義的拷貝構造函數
                {
                                _name = new char [10];
                                 if (_name != NULL )
                                {
                                                strcpy(_name, st._name);
                                                _age = st._age;
                                }
                }
                ~Student()
                {
                                 delete[] _name;                 //釋放動態內存
                }
                 void display()
                {
                                cout << _name << "--" << _age << endl;
                }
private:
                 char *_name;
                 int _age;
};

int main()
{
                 Student st1("lisi" , 20);
                 Student st2(st1);               //調用默認的拷貝構造函數創建一個新的對象
                system( "pause");
                 return 0;
}




在執行Student st2(st1)時調用自定義的拷貝構造函數,爲st2._name分配自己的動態內存。程序的執行過程如圖:


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