使用向量来最小化堆分配会导致seg错误

时间:2016-06-03 15:26:02

标签: c++ vector stack heap allocation

在一个函数中,我创建了一个具有大量空间的向量,我推送运行时确定的对象数量Edge)。但是,其他对象保持指向向量中Edges的指针。有时整个程序会因为指针变为无效而出现故障,我怀疑当向量达到容量并重新分配时会发生这种情况,从而使内存地址无效。

这有什么办法吗?或者是否有另一种将堆分配组合在一起的解决方案?

注意:这样做的主要动机是最小化堆分配,因为这会降低我的算法速度。最初我有vector<Edge *>,并且每个添加的元素都是单独分配的。批量分配大大提高了速度,但此处描述的vector方法使指针无效。

您的代码示例,根据要求: 这是我声明为堆栈var:

的向量
vector<Edge> edgeListTemp(1000); 

然后我使用rvalue重载添加它:

edgeListTemp.push_back(Edge{edge->movie, first, second});

Node个对象指向这些:

first->edges.push_back(&edgeListTemp.back());
second->edges.push_back(&edgeListTemp.back());

edges声明如下:

std::vector<Edge *> edges; /**< Adjacency list */

2 个答案:

答案 0 :(得分:2)

有几种可能的解决方案:

  • 如果您事先已经知道了元素的最大数量,请从一开始就对向量进行reserve;元素不会被重新分配,直到达到那个大小;
  • 如果您不知道元素的最大数量/不想出于性能原因而预先分配最大尺寸但是您只需从末尾添加/删除元素(或从矢量开始),使用std::deque代替。 std::deque保证只要你只从正面/背面推/弹,就不会使指向元素的指针无效;
  • std::list保证永远不会使对元素的引用无效,但它引入了几个严重的性能损失(没有O(1)寻址,每个节点有一个分配);
  • 如果要完全忽略该问题,请添加一个间接层,并将其存储到向量指针中,以存储到堆上分配的元素;更好的是,制作一个std::shared_ptr的向量,并始终使用它来保持对元素的引用;这显然有一个缺点,就是根据你的使用情况,需要为每个元素分配一个,这可能是也可能是不可接受的。

答案 1 :(得分:1)

std::deque一旦添加就不会移动元素,因此只要不删除引用的元素,迭代器和引用就是稳定的。

std::vector类似,std::deque提供随机访问迭代器。对双端队列的随机访问比std::vector慢一点,但仍然是O(1)。如果你需要稳定的参考,那么轻微的减速可能是可以接受的。

或者,您可以保留对向量的引用和向量中的索引,而不是指向元素的指针。