2017-02-24 61 views
1

考慮下面的代碼,其中分配大小5×3的2D std::vector<std::vector<int> >並打印各元素的存儲器地址:2d std :: vector連續內存?

#include <iostream> 
#include <vector> 

int main() { 
    int n = 5, m = 3; 
    std::vector<std::vector<int> >vec (n, std::vector<int>(m)); 

    for (int i = 0; i < n; ++i) { 
    for (int j = 0; j < m; ++j) { 
     std::cout << &(vec[i][j]) << " "; 
    } 
    std::cout << "\n"; 
    } 
} 

輸出:

0x71ecc0 0x71ecc4 0x71ecc8 
0x71ece0 0x71ece4 0x71ece8 
0x71ed00 0x71ed04 0x71ed08 
0x71ed20 0x71ed24 0x71ed28 
0x71ed40 0x71ed44 0x71ed48 

當然,對於一個固定的行,每列在內存中都是連續的,但行不是。特別是,每一行在前一行的開始之後是32個字節,但由於每行只有12個字節,這留下了20個字節的間隔。例如,因爲我認爲vectors分配連續的內存,我會期望第二行的第一個地址是0x71eccc。爲什麼不是這樣,vector如何決定給予多少差距?

+1

你爲什麼期待?向量開銷大小不爲0 ... –

+1

如果您希望數據連續,請分配一個大小爲「n * m」的單個向量,然後自己進行偏移量計算。 –

+0

或者使用'std :: array ,n>'爲0開銷。如果您需要動態容器,請執行@NeilButterworth建議的操作。 – user2176127

回答

2

向量的開銷大小不爲0.在向量的最後一個元素和下一個向量的第一個元素之間有24個字節。試試這個:

cout << sizeof(std::vector<int>) << endl; 

你會發現輸出爲24(很有可能爲你實現的std ::向量和編譯器等的)。 Live example which happens to match

你可以想象矢量佈局是這樣的:

enter image description here

如果你希望你的元素實際上是連續的,那麼你需要做的:

  1. 使用std::array<std::array<int>>爲無開銷( C++ 11 only)。請注意,這不能調整大小。
  2. 使用std::vector<int>和公式row * numRows + col訪問row, col的元素。
+0

請記住'sizeof(std :: vector )'是大量實現定義的。 – user2176127

+0

〜4字節的std :: vector通常用於分配器 – user2176127

+0

@Fantastic Mr Fox在'c8'和'e0'之間只有20個字節。 24在哪裏適合這裏? – bcf

1

同意Fox先生的結果和解決方案。不同意用來到達那裏的邏輯。

爲了調整大小的,一個std::vector包含連續的存儲器的動態分配的塊,因此,外vector有一個指針指向包含N個vector s表示是連續的存儲塊。但是,這些內部中的每一個都包含一個指向其自己的存儲塊的指針。所有N個存儲塊連續存在的可能性(沒有一些非常流行的自定義分配器伏都教)是驚人的小。 N vector的開銷是連續的。這些數據幾乎肯定不是,但可能是。

大部分。 std::vector中的std::array將是連續的,但是沒有任何東西阻止std::array的實現者輸入其他狀態信息,以防止std::array中的數組連續不斷。一個以這種方式編寫std::array的實現者是一個奇怪的頂部空間的使用者,或者解決一個非常有趣的問題。

+0

你的第二點是非常哲學的。雖然這個標準可能確實意味着'sizeof(std :: array )== sizeof(T)* N'成立,但沒有定義它,但實際上大多數主要編譯器都是這樣。 – user2176127

+0

@ user2176127同意。我不希望任何人不經過任何努力去找到或找到它,就會遇到這個問題。 – user4581301