c++ vector教學 - 假設STL向量存儲始終是連續的是否安全?




example insert (6)

如果你有一個已調整大小的STL向量,是否可以安全地獲取元素0的地址並假設其餘的向量將跟隨內存?

例如

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

Answers

C ++ 03標準添加了措辭,以明確向量元素必須是連續的。

C ++ 03 23.2.4第1段包含以下語言,該語言不在 C ++ 98標准文檔中:

vector的元素是連續存儲的,這意味著如果vvector<T, Allocator> ,其中T是除bool之外的某種類型,則它遵循所有0 <= n < v.size()的標識&v[n] == &v[0] + n 0 <= n < v.size()

Herb Sutter在他的一篇博文中討論了這一變化, Cringe not:矢量保證是連續的

......鄰接實際上是矢量抽象的一部分。 事實上,當發現C ++ 98標準並不完全保證連續性時,它是如此重要,C ++ 03標準被修改為明確添加保證。


std::vector保證項目存儲在連續的數組中,因此是數組的首選替換,也可用於與平台相關的低級代碼(如Win32 API調用)進行交互。 要獲取指向數組的指針,請使用:

&myVector.front();

是的,這是一個有效的假設(*)。

從C ++ 03標準(23.2.4.1):

向量的元素是連續存儲的,這意味著如果v是一個向量,其中T是除了bool之外的某種類型,那麼它服從所有0 <= n <v的身份&v [n] ==&v [0] + n 。尺寸()​​。

(*)...但是在向元素添加元素之後要注意重新分配的數組(使任何指針和迭代器無效)。


存儲始終是連續的,但它可能會隨著向量的容量的變化而移動。

如果在容量更改操作之前在元素零(或任何元素)上有指針,引用或迭代器,則它將失效並且必須重新分配。



這裡的大多數答案錯過了一個重要的細節:什麼?

你想在遏制者中保持什麼?

如果它是一個int s集合,那麼std::list將在每個場景中鬆散,無論您是否可以重新分配,您只能從前面移除等。列表遍歷速度較慢,每次插入都會花費您與分配器的交互...準備一個例子非常困難,其中list<int>跳過vector<int> 。 即使如此, deque<int>可能會更好或者更接近,而不僅僅是使用列表,這會帶來更大的內存開銷。

然而,如果你正在處理大量醜陋的數據 - 並且其中很少 - 你不想在插入時重新定位,並且由於重新分配而復制將會是一場災難 - 那麼你可能會更好一個list<UglyBlob>vector<UglyBlob>

但是,如果您切換到vector<UglyBlob*>或甚至vector<shared_ptr<UglyBlob> > ,則列表將落後。

因此,訪問模式,目標元素數量等仍然會影響比較,但在我看來 - 元素大小 - 複製成本等。





c++ stl vector