首頁  >  文章  >  後端開發  >  為什麼使用臨時物件初始化另一個物件時沒有呼叫 C 11 移動建構函式?

為什麼使用臨時物件初始化另一個物件時沒有呼叫 C 11 移動建構函式?

Mary-Kate Olsen
Mary-Kate Olsen原創
2024-11-05 05:06:02942瀏覽

Why is the C  11 Move Constructor Not Called When a Temporary Object is Used to Initialize Another Object?

C 11 移動構造函數未調用,預設構造函數首選

描述:
在C 11 中使用移動語義時,這是可能的遇到移動建構函式被意外跳過而轉而使用預設建構函式的情況。本文探討了這個問題,檢視了根本原因,並提供了解決方案。

問題:
考慮以下帶有輸出訊息的建構函式的類別X:

<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>

在下面提供的範例用法中,我們建立了三個物件:

<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>

但是,預期輸出並未顯示為z 呼叫的移動建構函數,而是使用預設建構函數。

標準一致性:
依據 C 11 標準 (§12.8.32),只要可能,移動語意應優先於複製語意。因此,在這種情況下,確實應該為 z 呼叫移動構造函數。

行為說明:
觀察到的行為是由於名為 copy elision。 C 11 允許編譯器在某些情況下省略複製/移動物件以提高效能。其中一種情況是,臨時物件將被複製/移動到具有相同 cv-unqualified 類型的物件。

在我們範例程式碼的最後一行, X("test") 建立一個臨時 X對象,並且它具有與目標 (z) 相同的 cv-unqualified 類型。因此,編譯器可以省略複製和移動建構函數,直接將臨時物件建構到 z 中,而不呼叫任何建構函數。

解:強制移動建構函式為呼叫後,我們可以使用std::move() 來明確指示應該要移動:

<code class="cpp">X z( std::move(X("test")) );</code>
透過此修改,將產生預期的輸出,確認移動構造函數的參與。

以上是為什麼使用臨時物件初始化另一個物件時沒有呼叫 C 11 移動建構函式?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn