C 11 未調用移動構造函數,首選預設構造函數
使用C 中的類別時,預計將使用移動構造函數高效的資源轉移。但是,在某些情況下,可能會意外選擇預設構造函數。
問題陳述
考慮以下類別:
<code class="cpp">class X { public: explicit X(char* c) { cout << "ctor" << endl; init(c); } X(X& lv) { cout << "copy" << endl; init(lv.c_); } X(X&& rv) { cout << "move" << endl; c_ = rv.c_; rv.c_ = nullptr; } const char* c() { return c_; } private: void init(char* c) { c_ = new char[strlen(c) + 1]; strcpy(c_, c); } char* c_; };</code>
With範例用法:
<code class="cpp">X x("test"); cout << x.c() << endl; X y(x); cout << y.c() << endl; X z(X("test")); cout << z.c() << endl;</code>
預期輸出為:
ctor test copy test ctor move test
但是,最後一行意外輸出「ctor」而不是「move」。
說明
根據 C 11 標準,在某些情況下應該呼叫移動構造函數。在這種情況下,當用 X("test") 建構 z 時應該會發生移動。但是,會呼叫預設構造函數。
此行為是由於複製省略造成的,這是一種最佳化技術,允許編譯器直接將臨時物件建構到目標中,而無需執行複製或移動操作。此最佳化適用於編譯器確定複製/移動操作是不必要的並且可以省略的情況。
在給定場景中,編譯器認為臨時 X("test") 是複製省略的候選者,因為它是在同一個表達式中自動建立和銷毀的。因此,它省略了移動操作並直接使用臨時資料建構 z,從而導致呼叫預設建構函數。
結論
複製省略可能會導致意外的結果使用移動構造函數時的行為,因為它可以防止在預期的情況下調用移動構造函數。編譯器可以根據其最佳化啟發式應用複製省略,這可能會因編譯器和最佳化設定而異。了解複製省略及其對程序行為的潛在影響非常重要。
以上是為什麼啟用複製消除後,C 11 中未呼叫移動建構函式?的詳細內容。更多資訊請關注PHP中文網其他相關文章!