2013-04-05 56 views
1

我知道std::vector元素在內存中保證是連續的。爲什麼矢量的矢量不能保證是連續的? (或者是嗎?)

那麼爲什麼你不能期望一個載體包含其他載體的總集合是連續的?

該向量應該保證其封閉項目的連續內存佈局,如果這些附件也是向量,那麼我會期望最頂端的向量的全部內容在連續的內存中。

但是在這個問題上似乎存在一些爭論,關於這是否屬實。一個人可以安全地依靠它嗎?一些人似乎go out of their way達到這一點,而我認爲這是有保證的。

+0

向量不直接存儲他們的數據。 – chris 2013-04-05 00:43:17

+0

謝謝,但我不太清楚你的意思。 – johnbakers 2013-04-05 00:44:58

+0

向量有一個指向他們數據的指針。我想有可能做一個分配器,可以做到這一點。 – chris 2013-04-05 00:46:25

回答

5

向量向量中的每個向量都是單獨的對象,因此它負責存儲。所以,不,這絕不是保證連續的,實際上我不能確定存在於外部矢量中的數據和內部矢量中的數據是否是連續的內存塊。

+1

自定義分配器可以管理它,如果它真的想。至於是否和爲什麼要這樣做... – cHao 2013-04-05 00:47:40

+0

是的,我想是的,但你仍然有風險,有對準問題或overocation。 – 2013-04-05 00:49:31

+0

好的,我現在明白了,謝謝。然而,我想像'vector '或'vector >'可以保證連續的內存,對嗎? – johnbakers 2013-04-05 01:17:12

2

向量是一個包含指向實際數組的指針的對象。

向量向量將是一個對象,其中有一個指向對象數組的指針,每個對象指向堆中其他地方的自己的數組。所以不,他們永遠不會像你問的那樣連續。

0

讓我們看看矢量的(邏輯的)存儲器佈局:

[size:4/8 bytes] 
[capacity:4/8 bytes] 
[other datamembers:n bytes] 
*[elements:size*sizeof(element) bytes] << one contiguous memory (pointer to heap) 

隨着矢量的矢量它看起來像這樣:

[size:4/8 bytes] 
[capacity:4/8 bytes] 
[other datamembers:n bytes] 
* [ 
    [Vector:0] 
     [size:4/8 bytes] 
     [capacity:4/8 bytes] 
     [other datamembers:n bytes] 
     *[elements:size*sizeof(element) bytes] << pointer to contiguous memory for elements 
    [Vector:1] 
     [size:4/8 bytes] 
     [capacity:4/8 bytes] 
     [other datamembers:n bytes] 
     *[elements:size*sizeof(element) bytes] 
    [Vector:2] 
     [size:4/8 bytes] 
     [capacity:4/8 bytes] 
     [other datamembers:n bytes] 
     *[elements:size*sizeof(element) bytes] 
    ... 
    ... 
] << contiguous memory of vectors 

這意味着一個矢量具有的指針,以連續存儲器存儲矢量,其中的每一個存儲它們的元素指向具有存儲元素的連續存儲器的另一個堆。

但是,如果你設法創建了一個分配器供向量使用,這樣它將分配連續的內存塊,但如果其中一個嵌套向量被刪除,那麼仍然會遇到問題,內存是不再連續。更不用說具有嵌套向量具有不同大小的情況。

根據您的使用情況,您可以使用客戶連續塊存儲器分配器作爲向量矢量,或者僅使用手動分配和取消分配一個連續存儲器塊的舊方式。

+0

一個向量實際上包含一個指向外部存儲塊的*指針*。這就是它可以調整自身的方式,甚至可以擁有*一組矢量 - 結構本身是一個常量。人們可以想象有一個包含所有元素的連續的內存塊,儘管如果沒有關於如何/何時分配東西的深入知識會很痛苦,並且調整任何矢量的大小可能會把所有元素都吹到地獄。 – cHao 2013-04-05 01:12:32

+0

@cHao:我實際上更新了我的回答,當你評論:) – 2013-04-05 01:16:03

0

問題是,矢量模板不包含它處理「嵌入」數據或直接。另一種說法是,vector類將其保存的數據數組包含在其中:vector類包含指向包含元素數組的內存區域的指針。它在結構上等同於:(即,constexpr

template <typename T> 
struct vector_eq { 
    T *ptr; 
}; 

和不

template <typename T> 
struct vector_neq { 
    T arr[SIZE]; 
}; 

這將需要SIZE到在編譯時已知的,被包括在struct arr元件。

我想象塔爾應該可以專門vector<vector<T>>包含一個指向一個單獨的內存塊,並有其方法返回的內存塊的vector<T>共享片特設的情況下,雖然它背後的邏輯很可能是有點毛茸茸的。

0

簡單說就是 - std :: vector保證元素是連續存儲的。但是,只包含元素的成員數據,在矢量的情況下,它的大小,容量和類似的東西,再加上指向實際矢量數據的指針。因此,一個向量向量會給你一個連續的向量向量,但是這些向量將在任意的內存地址上動態分配它們的數據。

由於在編譯時需要知道對象大小,因此不能讓對象具有不同的大小,唯一的方法是使用動態內存分配。如果您有一個固定大小的自定義矢量,它在內部不使用動態內存分配,那麼std::vector<customVector>會連續存儲customVectors,但您仍將擁有額外的輔助成員,它們將「中斷」customVector元素數據的實際連續性。

3

我認爲回答這個(相對於現有描述實現方式)的最正確的正式的方式是基於§23.3.6.1/ 1:

[...]的載體的元素被存儲連續的,這意味着如果vvector<T, Allocator>其中T是某種類型比其他布爾,那麼它服從所有0 <= n < v.size()身份

&v[n] == &v[0] + n 

注意這談到了向量的各個元素的&v[i]的地址和所暗示的,特別是該向量的每個元素都有固定大小sizeof(T)(因爲這是指針運算是如何工作的)。

這意味着矢量元素在運行時不可能改變大小。如果一個vector<vector<T>>被實現爲一個連續的內存塊,那麼外部向量的成員(它們本身就是向量)將被允許改變大小。

因此,必須有一個額外的間接級別,即各個向量必須包含某種指向存儲在不同位置的可變長度數據結構的指針。

+0

謝謝你。我意識到我可以通過做一些像'vector '或者'vector >這樣的東西來獲得我所追求的東西 - 任何一個都應該保證父向量中所有項的內存連續性,因此保留了「多維」狀結構,同時享受充分的內存連續性 – johnbakers 2013-04-05 01:46:20

+1

@SebbyJohanns當然。我的文章的目的是要表明你的問題的答案(「否」)直接來自標準,而不是通常如何實施載體。 – jogojapan 2013-04-05 01:48:41

+0

非常感謝 – johnbakers 2013-04-05 02:06:13