2015-02-11 13 views
2

我不得不遵循下面的一段代碼,我想知道標準對它的說明。它是未定義的行爲,已定義但未指定的行爲或明確定義的行爲?Rvalue綁定和移動的組合

using namespace std; 

struct Foo { 
    mutable int obj; 
    Foo(Foo&&) = default; 
    Foo(int arg) : obj(arg) {} 
    void f() const { obj *= 2; } 
}; 

int main() 
{ 
    Foo&& a = Foo(5); // Binds temporary, lifetime ends with program 
    const Foo& b = a; // Binds a, lifetime ends with program 
    Foo c(std::move(a)); // Moves from a 
    // a now in defined, but unspecified state 
    b.f(); // ?? 
    cout << b.obj << endl; // May output 10 
    return 0; 
} // End of lifetime of temporary 

註解和我對標準的理解和解釋是否正確?

+2

爲什麼地球上會有這種未定義的行爲?標量的移動狀態與移動前的狀態完全相同。這是一個副本。 – Columbo 2015-02-11 15:24:22

+0

「有效但未指定的狀態」是一個約定,後面是大多數標準庫類,關於它們的移動操作如何影響移出的對象。關於編譯器生成的移動構造函數沒有任何說明,或者從'Foo'移動的狀態。 – 2015-02-11 15:37:16

+0

@ T.C。啊,這就是我誤解了標準的地方......好吧,它不太容易閱讀 – WorldSEnder 2015-02-11 15:48:43

回答

5

move從一個值(rvalue ref構造,自然不會調用std::move)語義上意味着該值應該是有效的(具體而言,對於銷燬是有效的)但是未指定的狀態。

但是,C++中的move並沒有什麼魔力。這正是應該所做的,而不是語言強迫你做什麼。

move原始「標量」類型實例與複製它不同。

move ing類型從源到目的地執行每個組件的成員方式(和父級方式)move

=default只是意味着「用我的元素的移動構造函數」,這是一個int,而int移動構造函數...複印件(嗯,int移動構造函數不存在,但如果它做了它會做一個副本)。

move的語義,你必須離開源在一個有效的(也是最重要的可破壞的)狀態,需要與std容器和算法合理的方式進行交互,並std類型的行爲。


這一切都很好,但標準的後盾在哪裏?

[class.copy] /15.3

否則,基或構件與直接初始化:當您使用move=default在這種情況下的一類本條款結束

會發生什麼對應的基礎或x

而直接初始化的成員,告訴你如何從直接初始化int條款是:

[dcl.init] /17.8

否則,被初始化的對象的初始值是INI-tializer表達的(可能轉換的)值。

第二表達int a = 7; std::move(a);的值是7的a的值不改變,因爲標準不允許它。

搬家不是魔術。

(當前標準草案n4296的引述)