2016-03-21 20 views
5

これは、ほとんどのrelavant質問が既に尋ねられているようです。std :: move Vs std :: forward

Whats the difference between std::move and std::forward

しかし、それぞれの答えは異なっており、適用されると若干異なる事を言います。だから私は混乱している。

私は次のような状況があります。コンテナ

  • コピーのアイテムはコピー項目はので、私はその非常によく理解してC++ 03です。コンテナ
  • 構築物の項目は、私は信じているコンテナへの構築物の項目は、(私が間違っている場合はそう言って下さい)emplaceBackInternal()にTのコンストラクタへの2つの関数を使って引数を転送するために正しく完璧な転送を使用しています。
  • アイテムをコンテナに移動する
    アイテムがコンテナに移動することを理解しているようです。

コード:

template<typename T> 
class Container 
{ 
    std::size_t length; 
    T*   buffer; 

public: 
    void push_back(T const& value) 
    { 
     resizeIfRequired(); 
     pushBackInternal(value); 
    } 
    template<typename... Args> 
    void emplace_back(Args&&... args) 
    { 
     resizeIfRequired(); 
     emplaceBackInternal(std::forward<T>(arg)...); 
    } 
    void push_back(T&& value) 
    { 
     resizeIfRequired(); 
     // Is this forward correct or should it be move 
     moveBackInternal(std::forward<T>(value)); 
    } 
private: 
    void pushBackInternal(T const& value) 
    { 
     // Copy construct object into buffer; 
     new (buffer + length) T(value); 
     ++length; 
    } 
    template<typename... Args) 
    void emplaceBackInternal(Args&&... args) 
    { 
     // Construct object into buffer using arguments; 
     new (buffer + length) T(std::forward<T>(args)...); 
     ++length; 
    } 
    void moveBackInternal(T&& value) 
    { 
     // Move construct object into buffer; 
     // Is this forward correct or should it be move 
     new (buffer + length) T(std::forward<T>(value)); 
     ++length; 
    } 
}; 

私は、前述の答えで提供さ答えを3つの機能を比較するために、ここに3つのすべてが含まれます。主な理由は、moveconstructが同じように見えて、同じである必要があるように感じるということです。

Answer @Potatoswatter Score 67

のstd ::前方には、単一のユースケースがあります。この定義によると

テンプレート関数のパラメータをキャストするために、私のようにstd::movemoveBackInternal(T&& value)push_back(T&& value)の内側と を使用する必要があります値は関数のテンプレートパラメータではありません。

Answer @Howard Hinnant Score 38

Yは左辺値参照である場合、結果は左辺値式となります。 Yが左辺値のリファレンスでない場合、結果は右辺値(正確なxvalue)式になります。

は、この定義によって、私はstd::moveまたはstd::forwardのいずれかを使用することができるようです。

Answer @Bo Persson Score 11

のstd ::前方には、パラメータにそれが関数に渡された正確な方法を転送するために使用されます。

回答はリンクに従うとテンプレート化された関数がすべて使用されますが、std::forwardは受け入れ可能です。この場合

+0

...リンクされた回答によって答えられなかったあなたの質問は何ですか? – Barry

+0

まあまあ...答えは正しい!それぞれが異なる結果を指定します。 –

+0

彼らはすべて正しいです。 2つはちょうど 'std :: forward'の目的は転送参照のためであり、第3は' std :: forward'が何であるかを説明する時間を費やしています。 – Barry

答えて

5

void push_back(T&& value) 
{ 
    resizeIfRequired(); 
    moveBackInternal(std::forward<T>(value)); // (1)    
    moveBackInternal(std::move(value));  // (2) 

} 

std::forward<T>(value)std::move(value)は(それはそう(2)を使用して... (1)(2)間関係ありません)このシナリオで同じです。

moveは、xvalueへの無条件キャストです。その行は常に右辺値であるタイプT&&の式を与えます。

forwardは条件付きキャストです。 Tが左辺値参照型の場合、左辺値が得られます。それ以外の場合(参照型でも参照値型でもない場合)、rvalueが返されます。私たちの場合、Tは参照型ではありませんので、右辺値を取得します。

いずれにしても、私たちは同じポイントになります。moveBackInternalvalueと呼び、右値としてキャストします。ちょうどmove()はそこに着く簡単な方法です。 forward<T>作品、しかしそれは不要です。

+0

私はあなたの事務所(または投稿者)にいて、もっと良いテクニックについてホワイトボードで率直に議論をしたいと思っています。 - もし私が 'std :: move'と' std :: forward'の両方によって行われた作業がコンパイル時の作業であると仮定するならば。それで解決策(1)は、コードが 'emplace_back()'と同じに見えるので、より良いとは限りません。すべての状況で機能する1つのテクニックを持つことができる場合、なぜ2つの異なるテクニックが必要ですか?差異が少ないとコードを簡単に保守できますか? –

+0

@ LokiAstari主に意見に基づいているようです。無条件に移動するときに 'move()'を使う方が簡単です。 'push_back()'コードだけが動くので、なぜもっと複雑なキャストを使うのですか?最終的に、根本的に何かがあることがわかりました。私はそれがどのようにしてより良いものになるのか分かりません。そして、良くても悪くても、これは私たちが得たものです。 – Barry

+0

すべての入力をありがとう。正直言って私はまだ私の意見を形成しようとしているだけで、ここで悪魔を主張しようとしています。 :-) –