1、建構式
在C++面向物件程式設計中,通過建構式對物件行程初始化,它可以為物件在計算機記憶體中開辟記憶體空間,也可以為物件的資料成員提供初始值,建構式時一個與類同名,沒有回傳值的特殊成員函式,每當創建一個物件時(包括使用new動態創建物件),編譯系統就會自動呼叫建構式,建構式像類以外的一般函式和類成員函式一樣,可以多載和帶預設引數,建構式的多載為物件的生成提供了各種靈活的手段,
建構式分為預設建構式(默認建構式)和用戶自定義建構式,當程式員沒有定義建構式時,系統就會提供一個無參的預設建構式,如果用戶自定義了一個建構式,編譯器提供的預設建構式就自動消失了,

2、拷貝建構式(復制建構式)
拷貝建構式的功能是一個已有的物件來初始化一個被創建的同類的物件,是一種特殊的建構式,具有一般建構式的所有特性,其形參是本類物件的參考,用戶可以根據自己實際問題的需要定義特定的拷貝建構式,以實作同類物件之間資料成員的傳遞,如果用戶沒有宣告類的拷貝建構式,系統就會自動生成一個預設拷貝建構式,這個預設拷貝建構式的功能是把初始的每個資料成員的值都復制到新建立的物件中,拷貝建構式的宣告如下:
類名(型別 & 物件名);
class people
{
public:
void dipalay()
{
}
private:
int a;
char*name;
};
呼叫拷貝建構式有以下三種情況:
(1)用類的一個物件去初始化另一個物件時,
(2)物件作為函式引數傳遞時,呼叫拷貝建構式
(3)如果函式的回傳值是類的物件,函式呼叫回傳時,呼叫拷貝建構式,

3、淺拷貝和深拷貝
拷貝就是復制,創建副本,假設有物件A,A有屬性t1,t2,那么,我通過拷貝A,得到B,B應該也有屬性t1,t2,且A、B兩個物件的每個屬性,都應該是相同的,
對于基本型別的屬性t1,拷貝是沒有疑義的,簡單將值復制一份,就達到了拷貝的效果,而對于參考型別的屬性t2來說,拷貝就有了兩層含義,
第一層是,我只是將t2參考的地址復制一份給B的t2,確實達到了屬性相同的效果,可以理解為實作了拷貝,但是事實上,兩個物件中的屬性t2對應的是同一個物件,在B物件上對t2所指向的物件進行操作,就會影響到A物件中的t2的值,
第二層是,我將A的t2所指向的物件,假設為o1,完整復制一份,假設為o2,將新的o2的地址給B的t2,也達到了復制的效果,且對B的t2所指向的o2進行操作,不會影響到A的t2所指向的o1,
拷貝的兩層含義,對應了淺拷貝和深拷貝的概念,做了第一層,就是淺拷貝,做到第二層,就是深拷貝,
基于以上內容,很容易可以想到,淺拷貝比深拷貝要更快,但是,從拷貝的意義上來看,淺拷貝相較于深拷貝,要欠缺一點,

總結一下:
淺拷貝:位拷貝,拷貝建構式,賦值多載
多個物件共用同一塊資源,同一塊資源釋放多次,崩潰或者記憶體泄漏
深拷貝:每個物件共同擁有自己的資源,必須顯式提供拷貝建構式和賦值運算子,
簡而言之:深拷貝和淺拷貝可以簡單理解為:如果一個類擁有資源,當這個類的物件發生復制程序的時候,資源重新分配,這個程序就是深拷貝,反之,沒有重新分配資源,就是淺拷貝,

實體如下:
#include <iostream>using namespace std;
class CopyDemo{public: CopyDemo(int pa,char *cstr) //建構式,兩個引數 { this->a = pa; this->str = new char[1024]; //指標陣列,動態的用new在堆上分配存盤空間 strcpy(this->str,cstr); //拷貝過來 }
//沒寫,C++會自動幫忙寫一個復制建構式,淺拷貝只復制指標,如下注釋部分 //CopyDemo(CopyDemo& obj) //{ // this->a = obj.a; // this->str = obj.str; //這里是淺復制會出問題,要深復制 //}
CopyDemo(CopyDemo& obj) //一般資料成員有指標要自己寫復制建構式,如下 { this->a = obj.a; // this->str = obj.str; //這里是淺復制會出問題,要深復制 this->str = new char[1024];//應該這樣寫 if(str != 0) strcpy(this->str,obj.str); //如果成功,把內容復制過來 }
~CopyDemo() //解構式 { delete str; }
public: int a; //定義一個整型的資料成員 char *str; //字串指標};
int main(){ CopyDemo A(100,"hello!!!");
CopyDemo B = A; //復制建構式,把A的10和hello!!!復制給B cout <<"A:"<< A.a << "," <<A.str << endl; //輸出A:100,hello!!! cout <<"B:"<< B.a << "," <<B.str << endl; //輸出B:100,hello!!!
//修改后,發現A,B都被改變,原因就是淺復制,A,B指標指向同一地方,修改后都改變 B.a = 80; B.str[0] = 'k';
cout <<"A:"<< A.a << "," <<A.str << endl; //輸出A:100,kello!!! cout <<"B:"<< B.a << "," <<B.str << endl; //輸出B:80,kello!!!
return 0;}
根據上面實體可以看到,淺復制僅復制物件本身(其中包括是指標的成員),這樣不同被復制物件的成員中的對應非空指標會指向同一物件,被成員指標參考的物件成為共享的,無法直接通過指標成員安全地洗掉(因為若直接洗掉,另外物件中的指標就會無效,形成所謂的野指標,而訪問無效指標是危險的;除非這些指標有參考計數或者其它手段確保被指物件的所有權);
而深復制在淺復制的基礎上,連同指標指向的物件也一起復制,代價比較高,但是相對容易管理,
小結:
深拷貝和淺拷貝最根本的區別在于是否真正獲取一個物件的復制物體,而不是參考,
假設B復制了A,修改A的時候,看B是否發生變化:
如果B跟著也變了,說明是淺拷貝,拿人手短!(修改堆記憶體中的同一個值)
如果B沒有改變,說明是深拷貝,自食其力!(修改堆記憶體中的不同的值)
淺拷貝(shallowCopy)只是增加了一個指標指向已存在的記憶體地址,
深拷貝(deepCopy)是增加了一個指標并且申請了一個新的記憶體,使這個增加的指標指向這個新的記憶體,
使用深拷貝的情況下,釋放記憶體的時候不會因為出現淺拷貝時釋放同一個記憶體的錯誤,

如果你想更好的提升你的編程能力,學好C語言C++編程!彎道超車,快人一步!
【C語言C++學習企鵝圈子】,分享(原始碼、專案實戰視頻、專案筆記,基礎入門教程)
歡迎轉行和學習編程的伙伴,利用更多的資料學習成長比自己琢磨更快哦!
編程學習書籍:

編程學習視頻:

原文鏈接:https://mp.weixin.qq.com/s/emgZO229CTrtiJidAojpHA
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/250016.html
標籤:C++
