2012-01-14 14 views
10

私が間違っていない限り、どちらかというとうまくいくようです - もう一方を優先するベストプラクティスの理由はありますか?move 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

質問です:クラスのために実際に移動コンストラクタ/代入演算子ものがありますか? 彼らはあなたの目の角から見えるだけですか? リアル移動CTOR(#1)では

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

と代入演算子を移動し、あなたが正しく評価されるように、あなたは常に移動し、以来(#3)、あなたは、std::forwardを使用することはありません。

完全転送テンプレート(T&&)なしでは、std::forwardは決して意味をなさないことに注意してください。それは#2と#4の場合とまったく同じです。実際に右値(A-OK)または左値(それほど多くない)があるかどうかわからないので、ここではstd::moveを使用しません。

std::forwardの実際の動作については、this answer of mineを参照してください。

+0

あなたが正しいです、私は間違ったctorを見ていました。その質問にサンプルコードを追加しました。 – David

+0

@Dave: 'A'は推測されたテンプレートパラメータではないので、' std :: forward'の使い方は間違っています。それはちょうどそれが "std :: forward'の" rvalueへのキャスト "バージョンと一致することが起こります。 – Xeo

+0

私はあなたの文言を完全に理解しているわけではないかもしれませんが、動くctor(rvalueにキャスト)のstd :: moveと同じことを解決しません。サイドノート:VS2010は、#1が存在しない場合、あなたのオペレーター#2を移動コーターとして(間違って)受け入れているようです。 – David

関連する問題