2014-10-10 99 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