C++細節 深拷貝和淺拷貝(位拷貝)詳解
前提
在物件拷貝過程中,如果沒有自定義拷貝建構函式,系統會提供一個預設的拷貝建構函式,預設的拷貝建構函式對於基本型別的成員變數,按位元組複製,對於類型別成員變數,呼叫其相應型別的拷貝建構函式。
閱讀《高質量的c c++程式設計》,第9章有這樣一段話,類似的話在《c++primer》《effective C++》都有所提及,那就是拷貝建構函式問題,這個是類編寫者的一個基礎問題。
位拷貝(淺拷貝)舉例,a指向b,b的改變其實會影響a的改變,同時a原本指向的空間發生洩漏。
然後這種情況下有了深拷貝。
我對其繪製思維導圖,方便閱讀並用分點的方式進行總結;
何時呼叫?
以下情況都會呼叫拷貝建構函式:
一個物件以值傳遞的方式傳入函式體
一個物件以值傳遞的方式從函式返回
一個物件需要通過另外一個物件進行初始化。
淺拷貝:位拷貝,拷貝建構函式,賦值過載
多個物件共用同一塊資源,同一塊資源釋放多次,崩潰或者記憶體洩漏
深拷貝:每個物件共同擁有自己的資源,必須顯式提供拷貝建構函式和賦值運算子。
預設拷貝建構函式在拷貝過程中是按位元組複製的,對於指標型成員變數只複製指標本身,而不復制指標所指向的目標--淺拷貝。
我們用自己編寫的string舉例
class String { public: const char* c_str() { return _str; } String(const char* str = "") :_str(new char[strlen(str) + 1]) { strcpy(_str, str); } String(const String &s) :_str(NULL) { String tmp(s._str); swap(_str, tmp._str); } ~String() { if (_str) { delete[]_str; } } private: char* _str; };
通過開闢空間的方式,進行深拷貝
String s1("字串1");
String s2(s1);
cout << s2.c_str() << endl;
拷貝成功;
這種方式採取的 拷貝構造,注意這個
String(const String &s)
:_str(NULL)
{
String tmp(s._str);
swap(_str, tmp._str);
}
程式碼解析:其中this指向拷貝的物件,s指向試圖拷貝的原物件。(測試中的 this指向s2,s指向s1)
其中利用建構函式開闢空間,建立臨時的tmp,然後進行交換完成拷貝。
當然,我們也可以使用賦值操作符過載完成這一功能(如例子s1=s2)
String& operator =(const String& s)
{
if (this != &s)
{
String tmp(s._str);
swap(tmp._str, _str);
return *this;
}
}//呼叫構造析構
//本程式碼是tmp呼叫的建構函式
String(const char* str = "")
:_str(new char[strlen(str) + 1])
{
strcpy(_str, str);
}
/*String tmp(s._str)
呼叫這個建構函式,開闢空間,建立一個和s1一樣大小的空間,並拷貝值
*/
程式碼解析:
s1(this),s2(s)
建立tmp,tmp有和s2一樣大的空間,一樣的數值(呼叫建構函式),然後交換使s1(this)指向2號空間,獲得拷貝,tmp指向3號空間,tmp生命週期結束呼叫解構函式釋放,功能完成。
當然 賦值過載函式可以寫的更加簡潔
String &operator=(String s)
{
swap(_str, s._str);
return *this;
}
利用tmp的方式是 藉助建構函式,這一種方式則是藉助拷貝建構函式
相關推薦
面試:C++的深複製和淺複製(轉)
物件的構造,也可以由複製建構函式完成,即用一個物件的內容去初始化另一個物件的內容。此時,若物件使用了堆空間(注意和“堆物件”區分),就有深、淺複製的問題,不清楚則很容易出錯。 什麼是淺複製 預設複製建構函式:用一個物件的內容初始化另一個同類物件,也稱為預設的
C語言是什麼和vc6.0的安裝步驟詳解及第一個c程式
從今天開始,我每天會分享一些關於計算機的知識,包括C語言、Python、資料庫、網路、Linux、網路安全等相關知識;今天我們就以C語言來開始我們的交流、學習吧。 C語言是一門通用計算機程式語言,廣泛應用於底層開發。C語言的設計目標是提供一種能以簡易的方式編譯、
C++之函式物件/偽函式(Function Object)詳解(二)
除了自定義的函式物件,標準庫還為我們提供了一系列現成的函式物件, 比如常見的數學、邏輯運算等。例如:negate<type>(),plus<type>(),minus<type>(),multiplies<type&g
C++細節 深拷貝和淺拷貝(位拷貝)詳解
前提 在物件拷貝過程中,如果沒有自定義拷貝建構函式,系統會提供一個預設的拷貝建構函式,預設的拷貝建構函式對於基本型別的成員變數,按位元組複製,對於類型別成員變數,呼叫其相應型別的拷貝建構函式。 閱讀《高質量的c c++程式設計》,第9章有這樣一段話,類似的話在《c++pr
C++本質:類的賦值運算符=的重載,以及深拷貝和淺拷貝
fin 過程 種類 解決 對象的引用 執行 面向 鏈式 alt 關鍵詞:構造函數,淺拷貝,深拷貝,堆棧(stack),堆heap,賦值運算符摘要: 在面向對象程序設計中,對象間的相互拷貝和賦值是經常進行的操作。 如果對象在申明的同時馬上進行的初始化操作,則
C++的拷貝建構函式、operator=運算子過載,深拷貝和淺拷貝、explicit關鍵字
1、在C++編碼過程中,類的建立十分頻繁。 簡單的功能,當然不用考慮太多,但是從進一步深刻理解C++的內涵,類的結構和用法,編寫更好的程式碼的角度去考慮,我們就需要用到標題所提到的這些內容。 最近,在看單例模式,覺得十分有趣,然而如果想要掌握單例模式,就必須掌握這些內容。下
C++深拷貝和淺拷貝
C++中類的拷貝有兩種:深拷貝,淺拷貝:當出現類的等號賦值時,即會呼叫拷貝函式一:兩個的區別 1 在未定義顯示拷貝建構函式的情況下,系統會呼叫預設的拷貝函式——即淺拷貝,它能夠完成成員的一一複製。當資料成員中沒有指標時,淺拷貝是可行的;但當資料成員中有指標時,如果採用簡單的
C++裡面的深拷貝和淺拷貝
//拷貝有兩種:深拷貝和淺拷貝 //1.結構體中的深拷貝和淺拷貝 /* 淺拷貝:編譯器僅僅拷貝了結構體的值,而沒有建立新的記憶體空間,而是共享同一塊記憶體空間 。當結構體成員中含有buf的時候,拷貝之後釋放記憶體就不會出現問題,但是如果結構體中含有指標變數
關於C#中深拷貝和淺拷貝的認識
首先說我理解的一些基本概念(若有不對,歡迎指點) 記憶體:用來儲存程式資訊的介質。 指標:指向一塊記憶體區域,通過它可以訪問該記憶體區域中儲存的程式資訊。(C#也是有指標的) 值型別:struct(整形、浮點型、decimal的內部實現都是struct)、enum、可空型別
js中的深拷貝和淺拷貝
所有 object 簡單的 col images new color 其他 java 深復制和淺復制只針對像 Object, Array 這樣的復雜對象的。簡單來說,淺復制只復制一層對象的屬性,而深復制則遞歸復制了所有層級。 深淺拷貝 的主要區別就是:復制的是引用(地址)還
python學習系列--深拷貝和淺拷貝
深拷貝 淺拷貝 copy deepcopy概念普通情下,復制一個對象是不會新開辟內存空間的,只是把新的對象名稱指向原有的內存地址,這種操作其實不是算是拷貝,只是新的引用。把新的對象置於新的內存空間中,才是拷貝。在python中,深淺拷貝的區別實際上是拷貝的深度不同。操作常見的‘=’號就是一種拷貝方式。pyth
js 中引用類型 的深拷貝 和 淺拷貝的區別
而是 query reac cat 避免 string val this 臨時 一、曾經在讀JQ源碼的時候,對深拷貝算是有了一點的理解。我們在項目中是不是經常會遇到這樣的問題呢? 後臺返回一個數組對象(引用類型).次數在頁面渲染中需要對部分數據進行處理 比如:銀行卡6234
淺談Java中的深拷貝和淺拷貝
detail tle pac err @override 復制對象 deep har 間接 淺談Java中的深拷貝和淺拷貝(轉載) 原文鏈接: http://blog.csdn.net/tounaobun/article/details/8491392 假如說你想復制一
js的命名空間 && 單體模式 && 變量深拷貝和淺拷貝 && 頁面彈窗設計
但是 界面 ket 模式 utf 針對 col con prop 說在前面:這是我近期開發或者看書遇到的一些點,覺得還是蠻重要的。 一、為你的 JavaScript 對象提供命名空間 <!DOCTYPE html> <html> <head&
深拷貝和淺拷貝
深拷貝 淺拷貝 #include <stdio.h> int main(int argc, char *argv[]) { char *p1="123"; char *p2="123"; char *p3="456"; const char *p4="ab
python的復制,深拷貝和淺拷貝的區別(轉)
pla bsp space 數據 深拷貝 淺拷貝 deepcopy 拷貝 tro 在python中,對象賦值實際上是對象的引用。當創建一個對象,然後把它賦給另一個變量的時候,python並沒有拷貝這個對象,而只是拷貝了這個對象的引用 一般有三種方法, alist=[1,2,
python的深拷貝和淺拷貝
內存區域 需要 不可變 python3 復制 deepcopy 原始的 pen -m # 對象賦值 a = 'hello world' b = a print('a:',a,', b:',b) # a: hello world
Python-8 深拷貝和淺拷貝
water mark alt img 分享 深拷貝 所有 nag copy 淺拷貝 淺拷貝是對於一個對象的頂層拷貝通俗的理解是:拷貝了引用,並沒有拷貝內容 深拷貝 深拷貝是對於一個對象所有層次的拷貝(遞歸) 進一步理解拷貝 拷貝的其他方式 使用copy模
【轉載】圖解 Python 深拷貝和淺拷貝
div 原子 總結 但是 home 後來 idt scrip 需要 作者:田小計劃 出處:http://www.cnblogs.com/wilber2013/ Python中,對象的賦值,拷貝(深/淺拷貝)之間是有差異的,如果使用的時候不註意,就可能產生意外的結果。
對象的深拷貝和淺拷貝
height post ++ oid 一份 char log pac clu 在copy一個對象時(用一個對象去初始化另外一個對象),會調用類中的拷貝構造函數。如果我們自己沒有在類裏面寫拷貝構造函數,則C++編譯器會調用默認的拷貝構造函數。 淺拷貝:如果類定義的對象包含