C++編譯器選擇是否自動生成程式碼的背後邏輯
C++編譯器選擇是否自動生成程式碼的背後邏輯
編譯器會為class和struct(實際上兩者在C++中是一回事)自動生成建構函式、賦值操作符函式和解構函式。如果不是這樣,那麼開發者就必須自己寫一些枯燥冗餘的程式碼。然而編譯器並不總是生成這些預設程式碼,當它覺得它無法生成正確的程式碼時,它就會拒絕生成預設程式碼。在以下幾種情況中,編譯器會認為它無法生成正確的程式碼:
-
當開發者自己定義了建構函式時
編譯器會認為開發者想要自己定義預設建構函式(即無引數的建構函式),它無法猜測開發者的想法,因此不會再自動生成預設建構函式。
-
當開發者自己定義了移動建構函式時
編譯器認為開發者可能希望僅使用移動語義而禁止拷貝,所以拷貝構造和拷貝賦值都不再自動生成。移動賦值也不會自動生成,而是交給開發者自己來定義,因為開發者已經在定義移動語義了。
-
當開發者自己定義了移動賦值操作函式時
同上原因,拷貝構造和拷貝賦值不再預設生成。同樣的原因,移動建構函式也不會自動生成。
-
當開發者自己定義了拷貝建構函式
編譯器認為開發者已經自己定義了拷貝語義,無法保證能自動生成正確的移動語義的程式碼,所以不再自動生成此類程式碼。C++11標準規定也不要自動生成拷貝賦值操作符函式程式碼,因為使用者接管了拷貝語義的定義,但是Visual Studio仍然會生成拷貝賦值操作符函式程式碼。
-
當開發者自己定義了拷貝賦值操作函式時
同上原因,不再生成移動語義的程式碼。C++11標準規定也不要自動生成拷貝建構函式程式碼,因為使用者接管了拷貝語義的定義,但是Visual Studio仍然會生成拷貝建構函式程式碼。
-
當開發者自己定義了解構函式時
移動構造和移動賦值都涉及到資源從源物件移動到目標物件,對於源物件來說是釋放了對資源的所有權。而解構函式是釋放資源,所以既然使用者自己定義了用於釋放資源目的的解構函式,那麼說明移動的語義無法保持預設的實現,因此編譯器不再自動生成移動語義的程式碼。
-
當開發者自己定義了虛解構函式時
編譯器不再自動生成預設解構函式程式碼。