16

ベクトルを操作するコードがあります。

template<typename T>
void doVector(vector<T>& v, T&& value) {
    //....
    v.push_back(value);
    //...
}

通常の場合、 、または単に(新しい C++11 によると)push_backを使用する必要がありますか? また、それらはパフォーマンスにどのように影響しますか?forward(value)move(value)value

例えば、

v.push_back(forward<T>(value));
4

4 に答える 4

18

2 番目の引数がlvalueの場合、現在のコードはコンパイルされません。これは、がであることがT&&判明するためです。したがって、これはエラーです。X&TX&std::vector<T>std::vector<X&>std::vector<X> &

2 つのテンプレート パラメータを使用します。

template<typename T, typename V>
void doVector(vector<T> & v, V && value) 
{
    v.emplace_back(std::forward<V>(value));
}

Vとは異なる型を使用できるため、問題が解決するだけでなく、コードがより一般的なものになるTため、よりemplace_back理にかなっています。:-)

次の改善点:引数からemplace_back型のオブジェクトを作成する(おそらくコンストラクターを使用して) を使用しているため、この事実を利用して、可変引数関数にすることができます。Tvalue

template<typename T, typename ...V>
void doVector(vector<T> & v, V && ... value) 
{
    v.emplace_back(std::forward<V>(value)...);
}

次のように使用できるため、これはさらに一般的です。

struct point
{
    point(int, int) {}
};

std::vector<point> pts;
doVector(pts, 1, 2);

std::vector<int> ints;
doVector(ints, 10);

それが役立つことを願っています。

于 2013-08-13T16:41:09.397 に答える
7
  1. forward(value)完全な転送の意味が必要な場合に使用され、左辺値、右辺値などを保持します。

  2. 転送は、l-val、r-val、および参照引数のさまざまな組み合わせがある関数に対して複数のオーバーロードを記述することを避けるのに役立つため、非常に便利です。

  3. move(value)実際には、左辺値を右辺値にキャストするタイプのキャスト演算子です

  4. パフォーマンスに関しては、どちらもオブジェクトの余分なコピーを作成することを回避できます。これが主な利点です。

つまり、彼らは実際には2つの異なることをしています


通常の push_back と言うと、何を言っているのかわかりませんが、ここに 2 つの署名があります。

void push_back( const T& value );
void push_back( T&& value );

最初のものは通常のl-valを渡すことができますが、2番目の場合はl-valを「移動」するか、r-valを転送する必要があります。l-val を移動すると使用できなくなることに注意してください

おまけとして、r-val-refs の概念とそれに関連する他の概念を非常によく説明して いるリソースがあります。

他の人が示唆しているように、 emplace back の使用に切り替えることもできます。実際には、オブジェクトのコンストラクターに引数を完全に転送するため、必要なものを何でも渡すことができます。

于 2013-08-13T16:37:33.883 に答える
6
  • 転送参照であるパラメーターを渡すときは、常に を使用しますstd::forward
  • r-valueであるパラメーターを渡すときは、 を使用しますstd::move

例えば

template <typename T>
void funcA(T&& t) {
    funcC(std::forward<T>(t)); // T is deduced and therefore T&& means forward-ref.
}

void funcB(Foo&& f) {
    funcC(std::move(f)); // f is r-value, use move.
}

転送参照 (彼はこれをユニバーサル参照と呼んでいます) と、完全転送および/または をいつ使用するかを説明する Scott Meyers による優れたビデオを次に示しますstd::move

C++ and Beyond 2012: Scott Meyers - C++11 のユニバーサル リファレンス

使用の詳細については、次の関連する質問も参照してくださいstd::forward: forwards を使用する利点

于 2013-08-13T16:50:41.870 に答える