2014-10-10 102 views
1

我現在花了太多的時間試圖獲得以下代碼片段不段錯誤。有人能解釋我爲什麼這樣做嗎?移動向量結構的向量

我知道問題出在某個未初始化的內存中。

#include <iostream> 
#include <vector> 

using namespace std; 

struct node { 
    vector<int> parents; 
}; 

int main() { 
    vector<node> nodedb; 
    { 
     node df; 

     nodedb.push_back(move(df)); 
    } 

    { 
     node &existing_node = nodedb[0]; 

     for (int i = 0; i < 100; ++i) { 
      node df; 
      nodedb.push_back(move(df)); 

      existing_node.parents.push_back(0); 
     } 
    } 

    return 0; 
} 
+0

如果您事先知道向量的總大小,您可以對其調用保留,只要不超過向量的容量,迭代器不會失效。 – 2014-10-10 01:30:03

回答

5

當您在循環調用nodedb.push_back,這有現有的指針/迭代器失效的向量元素的潛力。如果向量需要超出其當前的內存分配,則會發生這種情況 - 分配了一塊新內存,向量內容被複制,舊內存被釋放。

這意味着在某個點existing_node變得無效,並且在此之後,取消引用它(通過existing_node.parents.push_back)會導致崩潰。

有你能解決這個問題的一些方法:

  1. 當你修改後的矢量,不要將一個向量元素的引用 - 通過它的索引(即nodedb[0].parents.push_back)直接引用元素。

  2. 正如以上@Neil Kirk建議的那樣,如果預先知道向量的大小,在添加項目之前調用vector.reserve意味着向量不會隨着其增長而重新分配內存。除了解決眼前的問題,這也會改善你的表現。然而,在改變矢量的同時保持對矢量項的引用仍然不是很好的做法。

  3. 正如@格雷格Hewgill提到的,你可以切換到使用list而非vector,如列表有現有的迭代器/引用列表元素不被(更改列表無效的財產,除非這些要素本身被擦除)。

+0

可能值得注意的是'list nodedb'不會受到這個問題的影響,並且原始代碼將按預期工作。 – 2014-10-10 01:29:02

+0

當然。謝謝。 – 2014-10-10 01:36:14