std::vector<int> a;
std::vector<int> b;
std::vector<int> c;
b
の要素とc
の要素をa
に追加して、これら3つのベクトルを連結したいと思います。これを行う最良の方法はどれですか、なぜですか?
1)vector::insert
を使用して:
a.reserve(a.size() + b.size() + c.size());
a.insert(a.end(), b.begin(), b.end());
a.insert(a.end(), c.begin(), c.end());
b.clear();
c.clear();
2)std::copy
を使用して:
a.reserve(a.size() + b.size() + c.size());
std::copy(b.begin(), b.end(), std::inserter(a, a.end()));
std::copy(c.begin(), c.end(), std::inserter(a, a.end()));
b.clear();
c.clear();
)std::move
を使用して(C++11
から):
a.reserve(a.size() + b.size() + c.size());
std::move(b.begin(), b.end(), std::inserter(a, a.end()));
std::move(c.begin(), c.end(), std::inserter(a, a.end()));
b.clear();
c.clear();
私の意見では、最初の解決策が最善の方法です。
vector<>::insert
は要素を追加するように設計されているため、最も適切なソリューションです。
宛先ベクトルでreserve
を呼び出してスペースを確保できますが、多くのベクトルを一緒に追加しない限り、多くの利点が得られない可能性があります。vector<>::insert
は、追加される要素の数を知っています。 1つのreserve
呼び出しのみを避けます。
注:これらがvector
のより複雑なタイプ(つまり、カスタムクラス、またはstd::string
)である場合、std::move
を使用すると、ニースが得られますコピーコンストラクターが回避されるため、パフォーマンスが向上します。ただし、int
のベクトルの場合、利点はありません。
注2:std::move
を使用すると、ソースvector
のコンテンツが使用できなくなることに注意してください。
移動せずにコピーしたい場合、これが最善の方法です。
a.reserve(a.size()+b.size()+c.size()); // Reserve space first
a.insert(a.end(),b.begin(),b.end());
a.insert(a.end(),c.begin(),c.end());
移動したい場合:
a.reserve(a.size()+b.size()+c.size()); // Reserve space first
a.insert(a.end(),std::make_move_iterator(b.begin()),
std::make_move_iterator(b.end()));
a.insert(a.end(),std::make_move_iterator(c.begin()),
std::make_move_iterator(c.end()));
b.swap(std::vector<int>()); // Clear and deallocate space
c.swap(std::vector<int>()); // Clear and deallocate space
更新:質問を数回編集して、ターゲットを移動させました。最初のオプションは、私の最初の提案と非常によく似ています。
更新2:C++ 11の時点で、 "空のベクターでスワップ"トリックを使用する必要がなくなる場合があります。ライブラリのvector
の実装に応じて、スペースをクリアおよび割り当て解除します。以下は、より直感的な方法で仕事をするかもしれません:
// Empty the vectors of objects
b.clear();
c.clear();
// Deallocate the memory allocated by the vectors
// Note: Unlike the swap trick, this is non-binding and any space reduction
// depends on the implementation of std::vector
b.shrink_to_fit();
c.shrink_to_fit();
insert
は、追加する要素の数を把握し、コピーを開始する前に適合するようにベクトルのサイズを変更できるため、最初の選択肢が最適です。他の人はその情報を持っていないので、コピー後にサイズ変更を行う可能性があります。これは、最初のサイズ変更や複数回のサイズ変更よりも遅くなります。
ただし、@ michaelgoldshteynが示唆するように、2つの挿入を行うため、最終サイズで配列を自分でサイズ変更して、1つのサイズ変更を保存することもできます。
b
とc
のデータをベクトルa
に本当に追加したい場合は、挿入を行う必要があります(実際には1。 ):
a.reserve( a.size() + b.size() + c.size() ); // preallocate memory (see why)
a.insert( a.end(), b.begin(), b.end() );
a.insert( a.end(), c.begin(), c.end() );
コンパイラーに応じてstd::copy
(あなたの2。)は通常、高速であるはずです。
std::vector
は常にメモリ内で連続している必要があります。move(C++ 11で定義)および終了サイズがわかっている場合は、 ベクターを予約する必要があります(ベクターの不要な再割り当てを回避します)。ただし、パフォーマンスが本当に心配な場合は、3つのstd::vector
そして、あなたが彼らのデータを読まなければならないとき、それらを繰り返します。