向量的移动结构

Moving structs of vectors

本文关键字:结构 移动 向量      更新时间:2023-10-16

我现在花了太多时间试图让下面的代码段不出错。有人能解释一下为什么会这样吗?

我知道这个问题存在于某个未初始化的内存中。

#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;
}

当您在循环中调用nodedb.push_back时,这可能会使指向向量元素的现有指针/迭代器失效。如果矢量需要增长到当前内存分配之外,就会发生这种情况——分配一个新的内存块,复制矢量内容,释放旧内存。

这意味着existing_node在某个时刻变得无效,在此之后,(通过existing_node.parents.push_back)取消引用它会导致崩溃。

有几种方法可以解决这个问题:

  1. 在修改向量时,不要保留对向量元素的引用——直接通过其索引(即nodedb[0].parents.push_back)引用该元素。

  2. 正如@Neil Kirk在上面所建议的,如果向量的大小是预先知道的,那么在添加项目之前调用vector.reserve意味着向量在增长时不需要重新分配内存。除了解决眼前的问题,这也将提高你的表现。然而,在更改矢量的同时保留对矢量项的引用仍然不是一种很好的做法。

  3. 正如@Greg Hewgill所指出的,您可以更改为使用list而不是vector,因为列表具有这样的属性,即对列表元素的现有迭代器/引用不会因列表的更改而无效(除非这些元素本身被删除)。