複製構造函數&深拷貝&淺拷貝

 一、複製構造函數
        1、作用:由編譯器調用來完成一些基於同一類的其他對象的構件及初始化;
         2、如果在類中沒有顯式聲明聲明一個複製構造函數,則編譯器默認生成一個複製構造函數進行對象間的bitwise copy,這個默認復                 制函數簡單的關聯了所有的類成員;
        3、c++中,有三種需要對象複製的情況,即複製構造函數會在以下情況中被調用:
               1):一個對象以值傳遞的方式傳入函數體;
               2):一個對象以值傳遞的方式從函數返回;
               3):一個對象需要通過另一個對象進行初始化;


#include<iostream>
using namespace std;
class Test
{
public:
int a;
Test (int x){a=x;}    
Test(Test &test){a=test.a;} //複製構造函數
};
void fun1(Test test){cout<<"fun1()..."<<endl;} //(1)值傳遞傳入函數體;

Test fun2(){Test t(2);return t;}                         //(2)值傳遞從函數體返回;

int main()
{
Test t1(1);
Test t2=t1;                                             //(3)用t1對t2初始化;
return 0;
}
 

二、系統自動提供一個默認的複製構造函數來處理複製,爲什麼需要自定義複製構造函數呢?
        1、淺拷貝&深拷貝:如果複製的對象中引用了某個外部內容(如例如分配在堆上的數據),則在複製這個對象的時候,淺拷貝即讓                                            新舊對象指向同一外部內容 ,深拷貝在複製這個對象的時候爲新對象製作了外部對象的獨立複製;

         通俗的理解即:如果一個類擁有資源(堆或其他系統資源),當這個類的對象在複製過程中進行了資源重新分配,這個過程即爲深拷貝;反之對象存在資源,但複製過程中並未複製資源的情況,即爲淺拷貝;



#include<iostream>
using namespace std;

class Test
{
public:
char *buf;
Test(void){buf=NULL;}   //無參構造函數;
Test(const char* str)   //有參構造函數;
{
buf=new char[strlen(str)+1]; //分配堆內存;
strcpy(buf,str);              //複製字符串;
        }
~Test()
{
if(buf!=NULL)
{
delete buf;     //釋放buf指向的堆內存;
buf=NULL;
}
}
  
};


int main()
{
Test t1("hello");
Test t2=t1;                     //調用默認複製構造函數;
cout<<"(t1.buf==t2.buf)?"<<((t1.buf==t2.buf)?"yes":"no")<<endl;

return 0;
}



出現問題:這裏程序崩潰發生在main()函數退出對象析構的時候。由於默認複製構造函數只是簡單的把兩個對象的指針做複製運算,他                   們指向同一個地址,當產生兩次析構時,釋放同一塊堆內存時發生崩潰。————淺拷貝帶來的問題;
solution:在類中添加自定義複製構造函數解決兩次析構問題;

                  Test (Test &test)
                  {
                           buf=new char[strlen(test.buf)+1];
                           strcpy(buf,test.buf);                                               
                  }
由於此時buf又分配了一塊堆內存來保存字符串,t1的buf和t2的buff分別指向不同的堆內存,析構時不會發生程序崩潰;————深拷貝;
發佈了31 篇原創文章 · 獲贊 14 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章