1、淺拷貝和深拷貝ide
所謂淺拷貝,就是由默認的拷貝構造函數所實現的對數據成員逐一賦值。若類中含有指針類型的數據,這種方式只是簡單的把指針的指向賦值給新成員,但並無給新成員分配內存,所以這種方式必然會致使錯誤。爲了解決淺拷貝出現的錯誤,必須顯示的定義一個拷貝構造函數,使之不但複製數據成員,並且爲對象分配各自的內存空間,這就是所謂的深拷貝。函數
2、淺拷貝url
淺拷貝就是由默認的拷貝構造函數所實現的數據成員逐一賦值。一般默認的拷貝構造函數可以勝任這個工做,可是若類中含有指針類型的數據,這種數據成員逐一賦值的方式將會產生錯誤。spa
例:指針
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)內存
{it
_name =st._name; //並無爲對象st2的數據成員_name分配新的內存空間class
_age =st._age;構造函數
}
主程序結束時,對象被逐個撤銷,先撤銷對象st2(由於st2後建立),撤銷前先調用析構函數,用delete運算符釋放所分配的內存空間;撤銷對象st1時,第二次調用析構函數,由於這時_name所指向的內存空間已經被釋放,企圖對同一塊內存空間釋放兩此,因此這時候程序出錯。
執行過程如圖:
3、深拷貝
爲了解決淺拷貝出現的錯誤,必須顯示的定義一個拷貝構造函數,使之不但能複製數據成員,並且爲指針分配各自的動態內存。
例:
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分配本身的動態內存。程序的執行過程如圖: