web-dev-qa-db-ja.com

STLベクターストレージが常に連続していると仮定しても安全ですか?

サイズが変更されたSTLベクトルがある場合、要素0のアドレスを取得し、ベクトルの残りの部分がメモリ内で続くと想定しても安全ですか?

例えば.

vector<char> vc(100);
// do some stuff with vc
vc.resize(200);
char* p = &vc[0];
// do stuff with *p
55
Ferruccio

はい、それは有効な仮定です(*)

C++ 03標準(23.2.4.1)から:

ベクトルの要素は連続して格納されます。つまり、vがbool以外の型であるベクトルの場合、すべての0 <= n <vに対して&v [n] ==&v [0] + nのアイデンティティに従います。 。サイズ()。

(*)...ただし、配列に要素を追加した後、配列が再割り当てされる(ポインターとイテレーターを無効にする)ことに注意してください。

72
Eclipse

C++ 03標準では、ベクトル要素が連続している必要があることを明確にするために文言が追加されました。

C++ 03 23.2.4段落1には、C++ 98標準文書ではnotである次の言語が含まれています。

vectorの要素は連続して格納されます。つまり、vが_vector<T, Allocator>_の場合、Tbool以外のタイプです。すべての0 <= n < v.size()のID _&v[n] == &v[0] + n_に従います。

Herb Sutterは、彼のブログエントリの1つでこの変更について語っています、 Cringe not:Vectorsは連続していることが保証されています

...隣接性は、実際にはベクトル抽象化の一部です。実際、C++ 98規格が完全に隣接性を保証していないことが発見されたとき、C++ 03規格が修正され、保証が明示的に追加されたことが非常に重要です。

27
Michael Burr

ストレージは常に連続していますが、ベクターの容量が変更されると移動する可能性があります。

容量変更操作の前にエレメント0(または任意のエレメント)にポインター、参照、またはイテレーターがあった場合、それは無効になり、再割り当てする必要があります。

13
Adam Holmberg
10
Jasper Bekkers

std::vectorは、アイテムが連続した配列に格納されることを保証します。したがって、配列の代替として推奨され、プラットフォームに依存する低レベルコード(Win32 API呼び出しなど)とのインターフェイスにも使用できます。配列へのポインタを取得するには、次を使用します。

&myVector.front();
4

はい。

常に隣接している必要があります

2
Keith Nicholas