默認拷貝構造函數,淺拷貝,深拷貝

類定義中,如果未提供自己的拷貝構造函數,則C++提供一個默認拷貝構造函數,就像沒有提供構造函數時,
C++提供默認構造函數一樣。
C++提供的默認拷貝構造函數工作的方法是:完成一個成員一個成員的拷貝,如果成員是類對象,則調用
其拷貝構造函數或者默認拷貝構造函數。
/*--------------------------------------
在默認拷貝構造函數中,拷貝的策略是逐個成員依次拷貝,但是,一個類可能會擁有資源,如果拷貝構造函數
簡單地製作了一個該資源的拷貝,而不對它本身分配,就得面臨一個麻煩的局面:兩個對象都擁有同一個資源
。當對象析構時,該資源將經歷兩次資源返還。
下面的程序描述了Person對象被簡單拷貝後,面臨析構時的困惑。
--------------------------------------------------*/
#include <iostream>
using namespace std;
class Person
{
public:
   Person(char *pN)
   {
    cout <<"Constructing "<<pN<<endl;
    pName=new char (strlen(pN)+1);
    if (pName!=0)
    {
     strcpy(pName,pN);
    }
   }
  
   ~Person()
   {
    cout<<"Destructing "<<pName<<endl;
    pName[0]='\0';
    delete   pName;
  
   }

protected:
   char *pName;
} ;
int main()

Person   p1("Randy");
Person   p2=p1;               //即Person p2 (p1);
}
/*
result is :
Constructing Randy
Destructing Randy
Destructing 
*/

/*---------------------------
程序開始運行時,創建p1對象,p1對象的構造函數從堆中分配空間並賦給數據成員pName,
執行,p2=p1時,因爲沒有定義拷貝構造函數,於是就調用默認拷貝構造函數,使得p2與p1完全一樣,
並沒有新分配堆空間給p2, p1與p2的pName都是同一個值。析構p2時,將堆中字符串清成空串,然後
將堆空間返還給系統; 析構p1時,因爲這是pName指向的是空串,所以第三行輸出中顯示的只是Destructing,
當執行 delete pName ; 按道理系統應該報錯,但在gcc中沒有

創建p2時,對象p1被複制了p2,但資源並未複製,因此,p1和p2指向同一個資源,這稱爲淺拷貝。
當一個對象創建時,分配了資源,這時,就需要定義自己的拷貝構造函數,使之不但拷貝成員,也拷貝資源
#include <iostream>
using namespace std;
class Person
{
public:
   Person(char *pN)
   {
    cout <<"Constructing "<<pN<<endl;
    pName=new char (strlen(pN)+1);
    if (pName!=0)
    {
     strcpy(pName,pN);
    }
   }
  
Person(Person& p)
{
cout <<"copying "<<p.pName<<"into its own block\n";
pName=new char [sizeof(p.pName)];
if (pName!=0)
   strcpy(pName,p.pName);


   ~Person()
   {
    cout<<"Destructing "<<pName<<endl;
    pName[0]='\0';
    delete   pName;
  
   }

protected:
   char *pName;
} ;
int main()

Person   p1("Randy");
Person   p2=p1;               //即Person p2 (p1);
}

result is :
Constructing Randy
copying Randyinto its own block
Destructing Randy
Destructing Randy

創建p2時,對象p1被複制給了p2,同時資源也作了複製,因此p1和p2指向不同的資源,這稱爲深拷貝。
堆內存並不是唯一需要拷貝構造函數的資源,但它是最常用的一個。打開文件,佔有硬設備(例如打印機
)服務也需要深拷貝。他們也是析構函數必須返還的資源類型。因此一個很好的經驗是:
如果你的類需要析構函數來析構資源,則它也需要一個拷貝構造函數。
因爲通常對象是自動被析構的,如果需要一個自定義的析構函數,那就意味着有額外資源要在對象被析構之前
釋放,此時,對象的拷貝就不是淺拷貝了。
---------------------------------------------*/
發佈了0 篇原創文章 · 獲贊 1 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章