首頁 > 後端開發 > C++ > 主體

為什麼在這種情況下我的 C 11 Move 構造函數沒有被呼叫?

Susan Sarandon
發布: 2024-11-05 01:49:02
原創
447 人瀏覽過

Why Doesn't My C  11 Move Constructor Get Called in This Case?

C 11 移動構造函數未調用,默認構造函數首選

問題

考慮以下類:

<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>
登入後複製

輸出是:

ctor
test
copy
test
ctor   <-- why not move?
test
登入後複製

在VS2010 中,使用預設設置,人們會期望最後一個物件(z)是移動構造的而不是預設的-建造的。使用 X z( move(X("test")) ) 會產生預期的輸出:ctor move test。這可能是 NRVO 的情況嗎?

問題

是否應該根據 C 11 標準呼叫移動構造函數?如果是這樣,為什麼不呼叫它?

回答

觀察到的行為是由於複製省略造成的。編譯器可以直接將臨時物件建構到要複製/移動到的目標中,從而省略複製/移動建構函數和析構函數呼叫。

第 12.8 節中概述了可以應用複製省略的情況。 C 11 標準第 32 條:

  • 在具有類別傳回類型的函數中,如果傳回表達式是與傳回型別相同類型的非揮發性自動物件。
  • 在 throw 表達式中,如果運算元是非揮發性自動對象,則其作用域未超出封閉的 try 區塊。
  • 當複製尚未綁定到引用的類別物件時/移動到具有相同類型的類別物件。
  • 當異常處理程序透過將異常聲明視為別名來聲明與異常物件相同類型的物件時。

在這種情況下,編譯器能夠省略臨時 X(「test」)和目標 z 之間的複製或移動操作,從而產生觀察到的行為。

以上是為什麼在這種情況下我的 C 11 Move 構造函數沒有被呼叫?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
作者最新文章
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!