首頁 > 後端開發 > C++ > 為什麼啟用複製消除後,C 11 中未呼叫移動建構函式?

為什麼啟用複製消除後,C 11 中未呼叫移動建構函式?

DDD
發布: 2024-11-06 09:46:02
原創
302 人瀏覽過

Why Is the Move Constructor Not Called in C  11 When Copy Elision Is Enabled?

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中文網其他相關文章!

來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板