0

私がC++でこのコンストラクターを持っているとしましょう:

 A::A( std::string const& name,
       std::string const& type,
       std::vector<B> const& b_vec,
       bool unique )
     : _name(name), _type(type), _b_vec(b_vec), _unique(unique)
     { };

引数が右辺値の場合にこのコンストラクターをオーバーロードしたいと思います(そこでmoveセマンティクスを使用したい)。

 A::A( std::string && name,
       std::string && type,
       std::vector<B> && b_vec,
       bool unique )
     : _name(name), _type(type), _b_vec(b_vec), _unique(unique)
     { };

上記の引数は、すべての引数が右辺値の場合は正常に機能しますが、次の例では、一部の引数のみが右辺値であると仮定します。

 // create some lvalues somehow
 std::string name   = "stack overflow";
 std::vector<B> vec = { ... }; // implementation of B's constructot is not important

 // call a mixed constructor
 A new_A_instance(name, "cool-website", vec, true);

'const&'は'&&'にバインドできませんが、'&&'は'const&'にバインドできるため、最初の(移動しない)コンストラクターが使用されることを理解しています。

(最初のコンストラクターの場合のように)コピーする代わりに(右辺値であるため)4つの引数のうち2つを移動できるため、これは最適ではないようです。

したがって、この特定の場合に演算子をオーバーロードすることはできますが、他の引数が右辺値であり、他の引数が左辺値である場合を簡単に想像できます。これらの各ケースでコンストラクターをオーバーロードする必要がありますか?これは、引数の数が増えるにつれて、組み合わせて非常に多くの過負荷につながります...

私は、より良い解決策があると感じています(おそらくテンプレートを使用していますが、私のテンプレートの知識は恥ずかしいほど低いです)。

注:この問題は、関数自体を移動するためにpass-by-ref関数をオーバーロードすることとは関係ありませんが、これは良い例であることがわかりました(特に、オーバーロードはそれほど違和感がないため。また、例としてコンストラクターを使用しただけですが、オーバーロードされた関数は何でもかまいません。

4

1 に答える 1

2

値渡し、これが移動セマンティクスの目的です。

 A::A(std::string name, std::string type, std::vector<B> b_vec, bool unique )
   : _name(std::move(name)), _type(std::move(type)), _b_vec(std::move(b_vec)),
     _unique(unique)
 { };

これは、すべての場合に期待される動作をします。一時的な値を渡すことで、コンパイラーはコピーの省略を実行できます。これはほとんどの場合実行されます。

2番目のコードでは、を使用しないため、コピーが作成されることに注意してくださいstd::move。あなたが書くときそれを理解してください

void foo(bar&& x)
{
    ...
}

次に、の本体にfoox左辺があります。名前の付いたオブジェクトは常に左辺値です。この本体の内部では、右辺値としてstd::move(x)渡す場合に使用する必要があります。x

于 2012-09-23T20:00:03.867 に答える