2013-08-13 9 views
16

私はベクトルで動作するコードがあります:通常のpush_backについてはいつ転送して移動する必要がありますか?

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

は、私は(新しいC++ 11による)forward(value)move(value)または単にvalueを使用する必要がありますか?どのようにパフォーマンスに影響を与えますか?あなたは完璧な転送の意味を必要とする場合例えば

は、

v.push_back(forward<T>(value)); 
+3

'emplace_back()'? – Mysticial

+0

'v.emplace_back(std :: forward (値))'。あなたが '移動 'した場合、左辺値から移動することになります(この場合、' T && 'は右辺値と左辺値の両方にバインドすることができます) – Praetorian

+0

@Praetorian push_backは、 'void push_back(value_type&& val);'これは 'emplace_back(forward )'と同じように動作するはずです。右ですか? – texasbruce

答えて

16

現在のコードはコンパイルされませんstd::vector<X> &。したがって、エラーです。

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

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

VT異なるタイプの可能性があるので、それは問題を解決していないという理由だけでそうemplace_backは、より理にかなって、それはコードをより汎用的になります。今:-)

次の改善:我々は(おそらくコンストラクタを使用して)引数valueからタイプTのオブジェクトを作成するemplace_backを使用していることから、私たちはこの事実を利用し、それ可変長機能作ることができます:

助け

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

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

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

希望:あなたのようにそれを使用することができて、さらに汎用的である

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

+0

答えはよく説明されていますが、emplace_backの無駄なラッパーを書いているわけではありません。 – aaronman

+1

@aaronman:元の質問を見てください。そこには、いくつかの他の仕事がpush_backのどちらかの側で行われるかもしれないことを暗示するコメントがあります。彼らはここには存在しませんが、私はそれが重要だとは思わない。 –

+0

@BleepBloop申し訳ありません私のミス – aaronman

6
  1. forward(value)は、L値、r値のようなものを保存し、使用されています。

  2. 転送は、それはあなたがL-VALの異なる組み合わせがある機能のための複数のオーバーロードを書いて避けるのを助けることができるので、R-VALと参照引数

  3. move(value)が実際にそのキャスト演算子の一種で非常に便利です性能の面でr値

  4. にL値をキャスト両方の主な利点であるオブジェクトの余分なコピーを避けます。

そこで彼らは本当にあなたが通常の一backを言うとき、私はここに、あなたは何を意味するかわからないんだけど別物


を行う2つのシグネチャがあります。

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

あなただけの任意の通常のL-VALを渡すことができますが、2番目のためにあなたは、L-VALを「移動」またはr-valのを転送しなければならない最初のもの。あなたは、L-VALを移動したら、あなたはここにボーナスのためにそれを

を使用することはできませんに注意してくださいすることはR-VAL-レフリーと非常によく、それらに関連付けられている他の概念の概念を説明するようでresourceです。他の人のよう

はあなたにもあなたが欲しいものは何でも、それを渡すことができることを意味し、オブジェクトのコンストラクタにそれ実際に完璧な前方の引数をするので、バック据え付ける使用に切り替える可能性が示唆されています。第2引数は左辺値ときT&&が順番にstd::vector<T>がある最初の引数と一致しませんstd::vector<X&>になることを意味しますX&するTニーズを意味しているX&であることが判明するので、

5
  • forwarding referenceのパラメータを渡す場合は、常にstd::forwardを使用してください。
  • r値のパラメータを渡す場合は、std::moveを使用します。

など。

C++ and Beyond 2012: Scott Meyers - Universal References in C++11

はまた、この関連を参照してください。

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

ここで完璧な転送および/またはstd::moveを使用すると、(彼は普遍的な参照を呼び出す)スコット・マイヤーズを説明フォワーディング参照することにより優れたビデオです使用の詳細についての質問std::forwardAdvantages of using forward

+0

'int'sを動かす点はあまりありません。 –

+0

@LightnessRacesinOrbit Fair point編集されました。 – Snps