1. 程式人生 > >C++細節 深拷貝和淺拷貝(位拷貝)詳解

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++編譯器會調用默認的拷貝構造函數。 淺拷貝:如果類定義的對象包含