1. 程式人生 > >c++中的拷貝建構函式原理

c++中的拷貝建構函式原理

有時候即使用同類物件初始化另一個物件,如下:

Type a;
Type b(a);

根據《深入探索C++物件模型》的描述,當型別展現出bitwise copy semantics(位逐次拷貝)時,編譯器不需要為該類合成一個預設拷貝建構函式。即只需將物件中的資料按位複製。

實際執行過程中,檢視彙編程式碼,編譯器未產生呼叫。也就是說,編譯器沒有為測試型別合成預設拷貝建構函式。

C++中,copy constructor 的實現有兩種:default memberwise initialization 和 user defined initialization 。前者由編譯器執行,後者由程式設計師自定義的copy constructor 執行。其中default memberwise initialization 又可劃分為bitwise copy 和 default copy constructor 。只有當用戶未定義自己的copy constructor,且當前型別不能展現出bitwise copy semantics,編譯器會合成default copy constructor 。

一個class 不展現出 bitwise copy semantics,有4種情況:

  1. 一個類內含一個物件成員而後者的型別宣告有一個拷貝建構函式(無論顯示宣告還是編譯器合成)。
  2. 一個類繼承自一個基類而後者存在一個拷貝建構函式。
  3. 一個類宣告一個或多個虛擬函式。
  4. 一個類派生自一個繼承串鏈,其中有一個或多個虛基類。

(實際上按照《深度探索C++物件模型》中的描述,預設建構函式也是未必會被合成出來,可合成預設建構函式的情況與上述相同。
原文:
C++新手一般有兩個常見的誤解:
1.任何class如果沒有定義default constructor ,就會被合成一個出來。
2.編譯器合成出來的default constructor 會顯示設定class 內每一個data member 的預設值。)

上述4種情況中,前兩者的編譯器將member object 或 base class 的copy constructor 呼叫操作安插到被合成的copy constructor 中。其他data member 也會被複制。

什麼情況下會用到copy constructor 呢?
1. 用物件顯示初始化操作。
2. 用物件初始化函式引數。
3. 用函式返回值初始化物件。

在這幾種情況下,編譯器會將這些操作做一些轉化。
1. 在顯示初始化物件時,會將定義的初始化操作剝奪,安插一個copy constructor 的操作。
2. 在初始化函式引數時,呼叫copy constructor 把實際引數直接建立在其應該的位置上。函式返回前,區域性物件的destructor 會被執行。
3. 在返回值用於初始化時,會為函式加上一個額外引數,型別是class object 的一個reference ,用來放置copy constructor 得到的返回值。在return 指令之前安插一個copy constructor 呼叫操作。

舉一個第三種情況的例子,比如:

Type func(int a,int b)
{
    Type x(a,b);
    //...
    return x;
}  

會被轉換為:

void func(Type & _result , int a , int b)
{
    Type x(a,b);
    //...
    _result.Type::Type(x);  //拷貝建構函式
    return;
}

從使用者層面可以做出優化,不需要呼叫copy constructor,而是呼叫constructor 。

Type func(int a,int b)
{
    return Type(a,b);
}

可以轉換為:

void func(Type & _result, int a, int b)
{
    _result.Type::Type(a,b);  //帶參建構函式
    return ;
}

因此,並非用函式返回值初始化物件時,總會呼叫copy constructor

相關推薦

C++拷貝建構函式、淺拷貝與深拷貝的詳解

拷貝建構函式呼叫時機: 1、物件需要通過另外一個物件進行初始 化:     T t1(10, 20);T t2(0, 0);T t3 = t1; // 拷貝建構函式呼叫的時機一:T t4(t2);  // 拷貝建構函式呼叫的時機 二:2、實參傳遞給形參時呼叫賦值建構函式 拷

C++ 拷貝建構函式被呼叫情況

1、當用類的一個物件初始化該類的另一個物件時.例如: Int main(){       Point A;       Point B(A);// } 2 如果函式的形參是類的物件,呼叫函式時,進行形參和實參結合時. void fun(Point P){ } int

為什麼C++拷貝建構函式的引數型別必須是引用?

  在C++中, 建構函式,拷貝建構函式,解構函式和賦值函式(賦值運算子過載)是最基本不過的需要掌握的知識。 但是如果我問你“拷貝建構函式的引數為什麼必須使用引用型別?”這個問題, 你會怎麼回答? 或許你會回答為了減少一次記憶體拷貝? 很慚愧的是,我的第一感覺也是這麼回答

c++拷貝建構函式原理

有時候即使用同類物件初始化另一個物件,如下: Type a; Type b(a); 根據《深入探索C++物件模型》的描述,當型別展現出bitwise copy semantics(位逐次拷貝)時,編譯器不需要為該類合成一個預設拷貝建構函式。即只需將物件中

批註:C++複製建構函式與過載賦值操作符總結:預設淺拷貝,帶指標的需要深拷貝

前言 這篇文章將對C++中複製建構函式和過載賦值操作符進行總結,包括以下內容: 複製建構函式和過載賦值操作符的定義;複製建構函式和過載賦值操作符的呼叫時機;複製建構函式和過載賦值操作符的實現要點;複製建構函式的一些細節。 複製建構函式和過載賦值操作符的定義 我們都知道

C++類拷貝建構函式詳解

a. C++標準中提到“The default constructor, copy constructor and copy assignment operator, and destructor are special member functions.[Note: T

C++建構函式拷貝構造和解構函式

我們使用內建型別建立物件的時候,因為內建型別是一個固定的型別(比如int),所以編譯器會為我們分配空間(4位元組),使得我們的程式碼正常執行。 而用類例項化出來的物件,因為是自定義型別,所以系統提前並不知道我們所定義出來的型別有多大,佔多少位元組。 在我們用

C++建構函式拷貝建構函式和賦值函式

一.建構函式 1.首先說明一下空類: 對於空類,編譯器會自動加入: 預設建構函式,拷貝建構函式,賦值建構函式,解構函式和取值函式 擴充:空類的大小為1.(因為每個例項在記憶體中都有獨一無二的地址,為了達到這個目的,編譯器往往會給空類增加一個位元組) 2

C++】拷貝建構函式

目錄 拷貝建構函式 拷貝建構函式的呼叫 預設的拷貝建構函式 深度拷貝  看完類的建構函式後,再來了解下拷貝建構函式。 拷貝建構函式 拷貝建構函式是一種特殊的建構函式。 (1)它是建構函式,所以函式名就是類名,沒有返回值; (2)它是特殊的建構函式,引

C++預設建構函式建構函式初始化列表

1、預設建構函式和建構函式 (1)建構函式:C++用於構建類的新物件時需要呼叫的函式,該函式無返回型別!(注意:是“無”! 不是空!(void))。 (2)預設建構函式:預設建構函式是在呼叫時不需要顯示地傳入實參的建構函式。 一個類如果自己沒有定義建構函式,則會有一個無參且函式體也是空的

C++建構函式和解構函式

1:建構函式 處理物件的初始化。特殊的成員函式,不需要使用者來呼叫,而是在建立物件的時候自動執行。 特點: ①與類名相同 ②沒有任何返回型別 ③定義時可以有引數,可以無引數 2:解構函式 語法 :~cl

C++為什麼建構函式不能定義為虛擬函式

關於C++為什麼不支援虛擬建構函式,Bjarne很早以前就在C++Style and Technique FAQ裡面做過回答 Avirtual call is a mechanism to get work done given partialinformation. In particular

淺談c++建構函式

下面所有的建構函式都將用Student這個類作為例子 class Student { private: static int count;//不屬於任何一個物件 std::string name; char *gender; i

C++的拷貝建構函式、operator=運算子過載,深拷貝和淺拷貝、explicit關鍵字

1、在C++編碼過程中,類的建立十分頻繁。 簡單的功能,當然不用考慮太多,但是從進一步深刻理解C++的內涵,類的結構和用法,編寫更好的程式碼的角度去考慮,我們就需要用到標題所提到的這些內容。 最近,在看單例模式,覺得十分有趣,然而如果想要掌握單例模式,就必須掌握這些內容。下

C++,編譯器會預設提供的建構函式有哪幾種? C++預設建構函式有幾種,詳細描述每一種。

答:         只有一種,預設建構函式。(不帶引數的建構函式) 答: 兩種:         1.不帶有任何引數的建構函式。比如 Example();如果使用者沒有定義任何建構函式,則編譯器會

C++建構函式與建立物件的(簡單)過程

<pre name="code" class="cpp">//構造方法 #pragma 在做遊戲的公司裡面初始化的方法有兩種風格 一種是init這是本來做蘋果轉過來的 另外一種是在構造方法裡面初始化 (這本來就是做C++的) #include <iostream> using

如何避免被C++預設拷貝建構函式忽悠?

一、背景介紹           因為工作關係,需要用到C++程式設計。對於我來說,雖然一直從事的是linux平臺下的嵌入式軟體開發,但深入用到C++的特性的地方並不多。對於C++,用得最多的無非是指標、封裝、繼承、組合以及虛擬函式。對於複製建構函式、過載操作符、智慧指標等

C++之拷貝建構函式和複製運算子過載

1、C++拷貝建構函式 拷貝建構函式是為了解決如神明物件時候就用一個已經存在的物件來初始化這個新的物件,如MyString A(B):這裡B是已經存在MyString物件。但是這裡需要注意拷貝建構函式裡面的內部實現細節。這裡面其實是在這個A物件類的定義中定義了拷貝建構函式的

C++下拷貝建構函式的引數型別必須是引用

摘自拷貝建構函式的引數型別必須是引用 在下面幾種情況下會呼叫拷貝建構函式: 1. 顯式或隱式地用同類型的一個物件來初始化另外一個物件。如上例中,用物件c初始化d; 2. 作為實參(argume

C++建構函式為什麼沒有返回值

class C{public:        C() : x(0) {}            //無參建構函式        C( int i ) : x(i) {}    //帶參建構函式private:         int  x}; 如果C的建構函式可以有返回值,比