配列の内容をループせずにC ++のstd :: vectorにコピーするにはどうすればよいですか?
質問
後で処理するために保存する必要があるプログラムの別の部分から関数に渡される値の配列があります。データを処理する前に関数が何回呼び出されるかわからないため、動的ストレージ構造が必要なので、 std :: vector
を選択しました。すべての値を個別に push_back
するために標準ループを実行する必要はありません。 memcpy
に似たものを使用してすべてをコピーできると便利です。
解決
配列と配列サイズを取得した後にベクトルを構築できる場合、次のように言うことができます:
std::vector<ValueType> vec(a, a + n);
... a
が配列で、 n
が含まれる要素の数であると仮定します。それ以外の場合は、 std :: copy()
w / resize()
がトリックを実行します。
値が従来のデータ(POD)型であることを確認できない限り、 memcpy()
から離れます。
また、これらのどれもforループを実際に回避しないことに注意してください。これは、コードでそれを確認する必要があるかどうかの問題です。 O(n)ランタイムのパフォーマンスは、値をコピーするために避けられません。
最後に、Cスタイルの配列はほとんどのSTLアルゴリズムに対して完全に有効なコンテナであることに注意してください。生のポインタは begin()
および( ptr + n
と同等です。 )は end()
と同等です。
他のヒント
ここには多くの答えがあり、それらのほぼすべてが仕事を成し遂げます。
ただし、誤解を招くアドバイスがあります!
オプションは次のとおりです。
vector<int> dataVec;
int dataArray[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
unsigned dataArraySize = sizeof(dataArray) / sizeof(int);
// Method 1: Copy the array to the vector using back_inserter.
{
copy(&dataArray[0], &dataArray[dataArraySize], back_inserter(dataVec));
}
// Method 2: Same as 1 but pre-extend the vector by the size of the array using reserve
{
dataVec.reserve(dataVec.size() + dataArraySize);
copy(&dataArray[0], &dataArray[dataArraySize], back_inserter(dataVec));
}
// Method 3: Memcpy
{
dataVec.resize(dataVec.size() + dataArraySize);
memcpy(&dataVec[dataVec.size() - dataArraySize], &dataArray[0], dataArraySize * sizeof(int));
}
// Method 4: vector::insert
{
dataVec.insert(dataVec.end(), &dataArray[0], &dataArray[dataArraySize]);
}
// Method 5: vector + vector
{
vector<int> dataVec2(&dataArray[0], &dataArray[dataArraySize]);
dataVec.insert(dataVec.end(), dataVec2.begin(), dataVec2.end());
}
長い話を短くするには、vector :: insertを使用する方法4を短くするのが、bsruthのシナリオに最適です。
以下に詳細を示します:
方法1 はおそらく最も理解しやすいでしょう。配列から各要素をコピーし、ベクターの後ろにプッシュするだけです。悲しいかな、遅いです。ループが存在するため(コピー機能で暗示される)、各要素は個別に処理する必要があります。配列とベクトルが連続したブロックであることがわかっているという事実に基づいて、パフォーマンスを改善することはできません。
方法2 は、方法1に対して推奨されるパフォーマンスの改善です。追加する前に、配列のサイズを事前に予約するだけです。大きな配列の場合、これは役立ちます 。ただし、ここでの最善のアドバイスは、プロファイリングで改善が得られる可能性がある(またはイテレーターが無効化されないようにする必要がある)場合を除き、リザーブを使用しないことです。 Bjarneは同意します。ちなみに、この方法はほとんどの場合最も遅いことを確認しましたが、方法1よりも定期的にかなり遅い理由を包括的に説明するのに苦労しています...
方法3 は古い方法です-問題にCを投げてください! PODタイプで問題なく高速に動作します。この場合、memcpyはベクターの境界外で動作し、ベクターにサイズが変更されたことを伝える方法がないため、resizeを呼び出す必要があります。 byteいソリューション(バイトコピー!)であることに加えて、これは PODタイプにのみ使用できることを忘れないでください。私はこのソリューションを使用しません。
方法4 が最適な方法です。その意味は明確で、(通常)最速であり、あらゆるオブジェクトに対して機能します。このアプリケーションでこのメソッドを使用することのマイナス面はありません。
方法5 は方法4の調整です。配列をベクトルにコピーしてから追加します。良いオプション-一般的に高速で明快です。
最後に、配列の代わりにベクトルを使用できることを知っていますか?関数がCスタイルの配列を想定している場合でも、ベクトルを使用できます。
vector<char> v(50); // Ensure there's enough space
strcpy(&v[0], "prefer vectors to c arrays");
誰かが助けてくれることを願っています!
既存のデータを置き換えるだけの場合は、これを行うことができます
std::vector<int> data; // evil global :)
void CopyData(int *newData, size_t count)
{
data.assign(newData, newData + count);
}
std :: copy が探しています。
自分の回答のみを編集できるので、質問に対する他の回答から複合回答を作成します。答えてくれた皆さんに感謝します。
std :: copy を使用すると、これはバックグラウンドで繰り返されますが、コードを入力する必要はありません。
int foo(int* data, int size)
{
static std::vector<int> my_data; //normally a class variable
std::copy(data, data + size, std::back_inserter(my_data));
return 0;
}
通常の memcpy を使用します。これはおそらく基本的なデータ型(つまりint)に最適ですが、構造体やクラスのより複雑な配列には使用されません。
vector<int> x(size);
memcpy(&x[0], source, size*sizeof(int));
int dataArray[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };//source
unsigned dataArraySize = sizeof(dataArray) / sizeof(int);
std::vector<int> myvector (dataArraySize );//target
std::copy ( myints, myints+dataArraySize , myvector.begin() );
//myvector now has 1,2,3,...10 :-)
memcpyは避けてください。本当に必要な場合を除き、ポインター操作を台無しにする理由はありません。また、POD型(intなど)でのみ機能しますが、構築が必要な型を扱っている場合は失敗します。
上記のメソッドに加えて、std :: Vector.reserve()、std :: Vector.resize()のいずれかを使用するか、ベクトルをサイズに合わせて構築し、ベクトルがデータを保持するのに十分な要素。そうでない場合、メモリが破損します。これは、std :: copy()またはmemcpy()のいずれにも当てはまります。
これがvector.push_back()を使用する理由です。ベクターの終わりを超えて書き込むことはできません。
さらに別の答えは、「私の関数が何回呼び出されるかわからない」と人が言ったので、そのようなベクトル挿入メソッドを使用して、値の配列をベクトルの最後に追加できます:
vector<int> x;
void AddValues(int* values, size_t size)
{
x.insert(x.end(), values, values+size);
}
この方法が好きなのは、ベクトルの実装がイテレータの型と型自体に基づいて値を挿入する最適な方法に最適化できるはずだからです。あなたはstlの実装についていくらか返答しています。
最速の速度を保証する必要があり、タイプがPODタイプであることがわかっている場合は、Thomasの答えにあるサイズ変更方法をお勧めします。
vector<int> x;
void AddValues(int* values, size_t size)
{
size_t old_size(x.size());
x.resize(old_size + size, 0);
memcpy(&x[old_size], values, size * sizeof(int));
}
ベクター内のアイテムの大きさを知っていると仮定すると:
std::vector<int> myArray;
myArray.resize (item_count, 0);
memcpy (&myArray.front(), source, item_count * sizeof(int));