私の質問は簡単です:std :: vector要素は連続していることが保証されていますか? Wordで、std :: vectorの最初の要素へのポインターをC配列として使用できますか?
私の記憶が私によく役立つなら、C++標準はそのような保証をしませんでした。ただし、std :: vectorの要件は、要素が連続していない場合に満たすことは事実上不可能でした。
誰かがこれを明確にすることはできますか?
例:
std::vector<int> values;
// ... fill up values
if( !values.empty() )
{
int *array = &values[0];
for( int i = 0; i < values.size(); ++i )
{
int v = array[i];
// do something with 'v'
}
}
これはC++ 98標準からは見逃されていましたが、後にTRの一部として追加されました。もちろん、今後のC++ 0x標準にはこれが要件として含まれます。
N2798(C++ 0xのドラフト)から:
23.2.6クラステンプレートベクトル[ベクトル]
1ベクトルは、ランダムアクセス反復子をサポートするシーケンスコンテナーです。さらに、最後の(償却済み)一定時間の挿入および消去操作をサポートします。中央に挿入して消去すると、線形の時間がかかります。ストレージ管理は自動的に処理されますが、効率を改善するためのヒントを提供できます。ベクトルの要素は連続して格納されます。つまり、vがTがbool以外のタイプのベクトルの場合、すべての0 <= n <vに対して&v [n] ==&v [0] + nのアイデンティティに従います。 。サイズ()。
他の答えが指摘したように、ベクトルの内容は連続していることが保証されています(boolの奇妙さを除く)。
私が追加したいコメントは、ベクターでメモリの再割り当てを引き起こす可能性のあるベクターで挿入または削除を行うと、保存されたすべてのポインターとイテレーターが無効になるということです。
実際、標準では、vector
がメモリ内で連続的であり、&a[0]
が配列を想定するC
関数に渡されることを保証しています。
この規則の例外はvector<bool>
で、bool
ごとに1ビットのみを使用します。したがって、連続メモリはありますが、bool*
として使用することはできません(これは広く考えられています誤った最適化と間違い)。
ところで、なぜイテレータを使用しないのですか?それが彼らの目的です。
他の人がすでに言ったように、vector
は内部的に連続したオブジェクトの配列を使用します。その配列へのポインターは、非constメンバー関数がIIRCと呼ばれる場合は常に無効として扱われるべきです。
ただし、例外があります!!
vector<bool>
には、スペースを節約するために設計された特殊な実装があり、各ブールは1ビットのみを使用します。基礎となる配列はブールの連続配列ではなく、vector<bool>
の配列演算はvector<T>
のようには機能しません。
(これはベクトルの特殊化にも当てはまると考えられます。常に新しいものを実装できるからです。ただし、std::vector<bool>
のみが、単純なポインター演算が機能しない標準の特殊化です。 )
このスレッドを見つけたのは、連続メモリを使用するベクターが利点であるユースケースがあるためです。
OpenGLで頂点バッファーオブジェクトを使用する方法を学んでいます。バッファーロジックを含めるラッパークラスを作成したので、必要なのは、floatの配列といくつかの構成値を渡してバッファーを作成することだけです。ユーザー入力に基づいて関数からバッファを生成できるようにしたいので、コンパイル時に長さがわかりません。このようなことをするのが最も簡単な解決策です:
void generate(std::vector<float> v)
{
float f = generate_next_float();
v.Push_back(f);
}
これで、ベクターの浮動小数点数を配列としてOpenGLのバッファー関連関数に渡すことができます。これにより、sizeofを使用して配列の長さを決定する必要もなくなります。
これは、フロートを格納するために巨大な配列を割り当てて、十分に大きくしたり、連続したストレージで独自の動的配列を作成したりすることを望んでいます。
はい、std :: vectorの要素は連続していることが保証されています。
ベクトルコンテナーは動的配列として実装されます。通常の配列と同様に、ベクトルコンテナーの要素は連続した格納場所に格納されます。つまり、イテレーターだけでなく、要素への通常のポインターのオフセットを使用して要素にアクセスできます。