直接初始化和複製初始化

2021-06-21 14:53:09 字數 2729 閱讀 8264

關於這個問題,國內外都有許多爭論,但我至今未找到滿意的答案,至於為為什麼,這就是今天要說明的。

可能大家都有看過c++ primer,我看的是第四版,中文版,英文水平不怎麼樣。

其中第13章,描述說,複製建構函式可用於:

1.根據另乙個同型別的物件顯式或隱式初始化乙個物件;

2.複製乙個物件,將它作為引數傳遞給乙個函式;

3.從函式返回時複製乙個物件;

4.初始化順序容器中的元素;

5.根據元素初始化列表初始化陣列元素;

關於第1點,當用於類型別物件時,直接初始化直接呼叫與實參匹配的建構函式,複製初始化總是呼叫複製建構函式。複製初始化首先使用指定的建構函式建立乙個臨時物件,然後用複製建構函式將那個臨時物件複製正在建立的物件:

string null_book = "9-999-99999-9";	//copy-initialization

sttring null_book("9-999-99999-9"); //direct-initialization

本來深信不疑的,但經過測試。問題出來了。如測試程式:

#include #include class a

a(const a &a):value_(a.value_)

};void test(a a)

a test()

int main()

; std::cin >> value;

}

輸出結果為:6個structure,很意外。

用vc2010,vc6,gcc測試結果均一致,跟c++ primer所說不一致。再仔細看。

但c++ primer 還有一句,當情況許可時,可以允許編譯器跳過複製建構函式直接建立物件,但編譯器沒有義務這樣做。

這什麼意思啊!

就是a a = 1; 是否執行是要看編譯器的啊,那上述的編譯器中均跳過複製建構函式。是否c++ primer有錯誤。

繼續下去,首先 ,這個網頁,說了copy_initialization ,並有gcc和clang編譯器,執行上面**結果也是一致,英文不怎樣所以看不太懂。

然後,又去看了 這上面第乙個答案說的跟c++ primer基本一樣。

說直接初始化是顯式呼叫匹配的建構函式。

而複製初始化是尋找乙個隱式的轉換,轉換成物件,(然後可能複製轉換後物件到被初始化的物件,所以有可能copy建構函式是必須的,但下面這種情況不是。)

struct b;

struct a ;

struct b

b(a const&)

};a::operator b()

int main()

// output:

gcc和clang編譯器輸出如**所示,但vs2010結果卻是,。

然後又去看了 , 這個guestgulkan 和我一樣迷茫,想找到乙個沒有跳過複製構造的例子。

然後又去看了

c++ primer 還有一段這樣說

「通常直接初始化和複製初始化僅在低級別優化上存在差異,然而,對於不支援複製的型別,或者使用非explicit建構函式的時候,它們有本質區別:

1 ifstream file1("filename")://ok:direct initialization

2 ifstream file2 = "filename";//error:copy constructor is private 」

在vs2010中也編譯不過,但編譯不過的原因並不是copy constructor is private,而是建構函式是顯式的,即加了explicit宣告。在vs2010中 copy constructor是私有的或有顯示呼叫宣告的,也能編譯過。

綜合權威觀點,也就是說複製初始化,不一定會呼叫copy建構函式。 但是就像c++還沒有規定int是佔幾位元組,只定義了最小為16位,但現在流行的編譯都通常認為是4位元組。所以必須得有個靠譜的結論。

不搞清這個問題,自己寫的**,都不知到底是怎樣的效果。除非只使用

a a; 

a b = a;

即型別相同複製初始化,這樣是只執行複製初始化的。不搞清這個問題,就不要使用不同型別的複製初始化了。

總後結論。

所以,在cl編譯器,可以認為複製初始化就是隱式的直接初始化。

即a(int value = 0):value_(value)

不變為explicit a(int value = 0):value_(value) 的情況下。

a a = 1 和 a a(1)類似的複製初始化和直接初始化沒有區別的。

而在gcc/clang 編譯器上,除了 stackoverflow 所說的那個有型別操作符轉換這種情況的之外,還有個不同就是:

gcc/clang明明做了這個義務,即跳過了執行複製構造,但在編譯的時候,還會檢查其是否必須顯示呼叫和是否公開方法。

即把 a(const a &a):value_(a.value_)

變為explicit a(const a &a):value_(a.value_) 或 把這個方法變為非公開,則會產生編譯錯誤。

除了這兩點 和 cl編譯器的那點,a a=1 和 a a(1)類似的複製初始化和直接初始化沒有區別的。

只是個c++初學者,有錯誤請指出。

直接初始化和複製初始化

1 classtest ct1 ab 這條語句屬於直接初始化,它不需要呼叫複製建構函式,直接呼叫建構函式classtest const char pc 所以當複製建構函式變為私有時,它還是能直接執行的。2 classtest ct2 ab 這條語句為複製初始化,它首先呼叫建構函式classtest ...

C 直接初始化和複製初始化

在c 裡,物件初始化是乙個非常重要但又容易令人混淆的問題。這裡是自己的一些總結。一。初始化與賦值的含義 初始化 包括建立 或說定義 物件並且賦給初值。如果乙個物件只被建立而沒有被初始化,則該變數只能用於被賦值 賦值 擦除物件的當前值並用新值代替。二。內建型別 一 直接初始化 1.空初始化 即無引數無...

直接初始化與拷貝 複製 初始化

認識這兩種初始化有助於我們加深對語言的理解,可以更好的優化 我們常見的幾種初始化的形式 string str1 first 拷貝初始化,編譯器允許把這句話改寫為string str first 但是string 類必須有 public 的拷貝 移動 建構函式 string str2 10,a 直接初...