2012-01-14 24 views
10

除非我錯了,否則看起來好像工作得很好 - 是否有一個最佳實踐理由更喜歡一個比另一個?我應該在移動ctors /賦值運算符中使用std :: move還是std :: forward?

例子:

struct A 
{ 
    A(){} 
    A(const A&){ std::cout << "A(const A&)\n"; } 
    A(A&&){ std::cout << "A(A&&)\n"; } 
}; 

struct B 
{ 
    B(){} 
    B(const B& right) : x(right.x){ std::cout << "B(const B&)\n"; } 
    B(B&& right) : x(std::forward<A>(right.x)){ std::cout << "B(B&&)\n"; } 

    A x; 
}; 

struct C 
{ 
    C(){} 
    C(const C& right) : x(right.x){ std::cout << "C(const C&)\n"; } 
    C(C&& right) : x(std::move(right.x)){ std::cout << "C(C&&)\n"; } 

    A x; 
}; 

struct D 
{ 
    D(){} 
    D(const D& right) : x(right.x){ std::cout << "D(const D&)\n"; } 
    D(D&& right) : x(right.x){ std::cout << "D(D&&)\n"; } 

    A x; 
}; 

int main() 
{ 
    std::cout << "--- B Test ---\n"; 
    B b1; 
    B b2(std::move(b1)); 
    std::cout << "--- C Test ---\n"; 
    C c1; 
    C c2(std::move(c1)); 
    std::cout << "--- D Test ---\n"; 
    D d1; 
    D d2(std::move(d1)); 
} 

輸出:

--- B Test --- 
A(A&&) 
B(B&&) 
--- C Test --- 
A(A&&) 
C(C&&) 
--- D Test --- 
A(const A&) 
D(D&&) 

回答

14

的問題是:那些真正的移動構造函數/賦值運算符的類? 或者他們只看起來像從你的眼角?

struct X{ 
    X(X&&); // move ctor #1 

    template<class T> 
    X(T&&); // perfect forwarding ctor #2 

    X& operator=(X&&); // move assignment operator #3 

    template<class T> 
    X& operator=(T&&); // perfect forwarding ass. operator #4 
}; 

真正移動構造函數(#1)和移動賦值運算符(#3),你將永遠不會使用std::forward,因爲,正如你正確評估,你總是會移動。

請注意,如果沒有完美的轉發模板(T&&),std::forward永遠沒有意義。 #2和#4就是這種情況。在這裏,你永遠不會使用std::move,因爲你不知道你是否真的有一個右值(A-OK)或左值(不是很多)。

有關std::forward實際工作方式的說明,請參閱this answer of mine

+0

你說得對,我正在看錯誤的ctor。我爲這個問題添加了一些示例代碼。 – David 2012-01-14 06:01:54

+0

@Dave:您使用'std :: forward'是錯誤的,因爲'A'不是推導出的模板參數。它恰好是它匹配「std :: forward」的「cast to rvalue」版本。 – Xeo 2012-01-14 06:13:09

+0

我可能並不完全理解你的措辭,但不會轉發(並且它不會*總是*)解決std :: move中移動ctor(轉換爲右值)的相同內容?附註:當#1不存在時,VS2010似乎(錯誤地?)接受你的操作員#2作爲移動控制器。 – David 2012-01-14 06:22:56

相關問題