2013-02-24 73 views
1

我試圖使用其它項目的代碼,他們有這種形式的結構:矢量調整大小VS儲備嵌套向量

struct data{ 
    std::vector<sparse_array> cols,rows; 
} 

struct sparse_array { 
    std::vector<unsigned int> idxs; 
    std::vector<double> values; 

    void add(unsigned int idx, double value) { 
     idxs.push_back(idx); 
     values.push_back(value); 
    } 
} 

對於我的代碼,我嘗試使用下面幾行:

data prob; 
prob.cols.reserve(num_cols); 
prob.rows.reserve(num_rows); 

// Some loop that calls 
prob.cols[i].add(idx, value); 
prob.rows[i].add(idx, value); 

而當我輸出的值,prob.rows[i].value[j]到一個文件,我得到全零。但是,當我使用resize而不是reserve時,我得到了我閱讀的實際值。有人能給我一個解釋嗎?

+0

見類似的問題:選擇向量之間::調整()和載體::儲備()(http://stackoverflow.com/q/7397768/ 1168156)和[std :: vector :: resize()與std :: vector :: reserve()](http://stackoverflow.com/q/13029299/1168156) – LihO 2013-02-24 02:10:14

回答

3

函數reserve()只是簡單地分配一個足夠大的內存連續區域來容納指定的項目數,並將向量的舊內容移動到這個新塊中,從而確保在插入時不會再進行向量存儲的重新分配只要不超過規定的容量。此函數用於減少重新分配的次數(這也會使迭代器失效),但不會在矢量的末尾插入任何新項目。

從C++ 11標準,段落23.3.6.3/1約reserve()

,通知在尺寸的變更預定的向量,以便它可以相應地管理存儲 分配A指令。如果重新分配發生,reserve(),capacity()大於或等於備用參數;並且等於之前的capacity()的值。當且僅當當前容量小於reserve()的參數時,此時重新分配發生。如果除非由非CopyInsertable類型的移動構造函數引發異常,則不會有效果。

請注意,這樣做prob.cols[i].push_back(idx, value);你很可能得到未定義行爲,因爲i可能是越界-的索引。

在另一方面,功能resize()確實插入項目,在您向量的末尾,使載體的最終大小將是你指定的(這意味着它甚至可以擦除元素,如果你指定比當前尺寸小的尺寸)。如果您對resize()的調用沒有指定第二個參數,則新插入的項目將進行值初始化。否則,它們將根據您提供的值進行復制初始化。

從C++ 11標準,段落23.3.6.3/9約resize():相當於erase(begin() + sz, end())

如果sz <= size(),;。如果size() < sz,則將 sz - size()值初始化的元素附加到該序列。

所以總結起來,之所以調用resize()給出預期的結果之後訪問您的載體是項目實際上是被添加到載體。另一方面,由於reserve()的調用不會添加任何項目,因此對後續的訪問不存在的元素會導致您的未定義行爲

+0

+1有關詳細說明 – LihO 2013-02-24 02:06:59

0

如果向量爲空,則std::vector::resize(n)通過在最後插入n新元素來擴展此向量的內容。 std::vector::reserve(n)只重新分配您的矢量用於存儲其元素的內存塊,以便它足夠大以容納n元素。

然後當您撥打prob.cols[i]時,您嘗試訪問索引i處的元素。如果您以前使用過reserve,則會導致訪問尚未存在元素的內存,這會產生未定義的行爲

所以只需使用resize在這種情況下:)