64

ある範囲の要素をベクトルに挿入する次のプログラムについて考えてみます。

vector<string> v1;
vector<string> v2;

v1.push_back("one");
v1.push_back("two");
v1.push_back("three");

v2.push_back("four");
v2.push_back("five");
v2.push_back("six");

v1.insert(v1.end(), v2.begin(), v2.end());

これにより、範囲が効率的にコピーされ、範囲全体にターゲットベクトルに十分なスペースが割り当てられるため、最大1つのサイズ変更が必要になります。ここで、範囲をベクトルに移動しようとする次のプログラムについて考えてみます。

vector<string> v1;
vector<string> v2;

v1.push_back("one");
v1.push_back("two");
v1.push_back("three");

v2.push_back("four");
v2.push_back("five");
v2.push_back("six");

for_each ( v2.begin(), v2.end(), [&v1]( string & s )
{
    v1.emplace_back(std::move(s));
});

これは正常な移動を実行しますが、ターゲットベクトル内のスペースの事前割り当てに関してinsert()が持つ利点を享受しないため、操作中にベクトルのサイズを数回変更できます。

だから私の質問は、範囲をベクトルに移動できる同等の挿入物はありますか?

4

2 に答える 2

99

と一緒に使用move_iteratorinsertます:

v1.insert(v1.end(), make_move_iterator(v2.begin()), make_move_iterator(v2.end()));

24.5.3 の例はほぼこれです。

vector::insert(a)イテレータタグディスパッチを使用してランダムアクセスイテレータを検出し、サイズを事前に計算し(コピーする例ではそうすると想定しています)、(b)move_iteratorイテレータを保持すると、必要な最適化が得られますラップする反復子のカテゴリ (標準で必要)。

あいまいな点:vector::insertソースから emplace できると確信しています (ソースは宛先と同じタイプであるため、ここでは関係ありません。したがって、emplace はコピー/移動と同じですが、に関連しますそれ以外は同一の例)。そうする必要があるというステートメントをまだ見つけていません。i,j渡された反復子ペアの要件がfromでinsertあるという事実から推測しただけです。TEmplaceConstructible*i

于 2012-05-23T12:48:20.167 に答える
41
  1. std::move事前割り当てのあるアルゴリズム:

    #include <iterator>
    #include <algorithm>
    
    v1.reserve(v1.size() + v2.size()); // optional
    std::move(v2.begin(), v2.end(), std::back_inserter(v1));
    
  2. 以下はさらに柔軟性があります。

    v1.insert(v1.end(), 
         std::make_move_iterator(v2.begin()), 
         std::make_move_iterator(v2.end()));
    

    Steve Jessopは、それが何をするのか、そしておそらくそれがどのように行うのかについての背景情報を提供しました。

于 2012-05-23T12:45:55.830 に答える