指向std :: vector和std :: list元素的指针

时间:2010-07-20 07:23:48

标签: c++ stl pointers stdvector

我的std::vector包含某些类ClassA的元素。另外,我想使用std::map<key,ClassA*>创建一个索引,它将一些键值映射到指向向量中包含的元素的指针。

当向量的末尾添加(不是插入)时,是否保证这些指针保持有效(并指向同一个对象)。即,以下代码是否正确:

std::vector<ClassA> storage;
std::map<int, ClassA*> map;

for (int i=0; i<10000; ++i) {
  storage.push_back(ClassA());
  map.insert(std::make_pair(storage.back().getKey(), &(storage.back()));
}
// map contains only valid pointers to the 'correct' elements of storage

如果我使用std::list代替std::vector

,情况如何?

7 个答案:

答案 0 :(得分:25)

向量 - 否。因为向量的容量永远不会缩小,所以即使删除或更改了元素,也可以保证引用,指针和迭代器保持有效,只要它们引用操作元素之前的位置即可。但是,插入可能会使引用,指针和迭代器无效。

列表 - 是的,插入和删除元素不会使指针,引用和其他元素的迭代器无效

答案 1 :(得分:9)

据我所知,没有这样的保证。向向量中添加元素将导致元素重新分配,从而使地图中的所有指针无效。

答案 2 :(得分:6)

使用std::deque!仅使用push_back()时,元素的指针是稳定的。

注意:元素的迭代器可能无效!指向元素的指针不会。

编辑:此答案解释了原因:C++ deque's iterator invalidated after push_front()

答案 3 :(得分:3)

我不确定它是否有保证,但实际上storage.reserve(needed_size)应该确保不会发生重新分配。

但为什么不存储索引呢? 通过将索引添加到开始迭代器(storage.begin()+idx)可以很容易地将索引转换为迭代器,并且通过首先取消引用它,然后获取其地址(&*(storage.begin()+idx)),可以很容易地将任何迭代器转换为指针。

答案 4 :(得分:1)

只要让它们成为存储指针,就可以在不需要时明确删除对象。

std::vector<ClassA*> storage;
std::map<int, ClassA*> map;

for (int i=0; i<10000; ++i) {
  ClassA* a = new ClassA()
  storage.push_back(a)
  map.insert(std::make_pair(a->getKey(), a))
}
// map contains only valid pointers to the 'correct' elements of storage

答案 5 :(得分:1)

从其中一个评论到另一个答案,似乎所有你想要的是集中(轻松)内存管理。如果确实如此,您应该考虑使用预先打包的解决方案,例如boost pointer container库,并尽可能简化您自己的代码。

请特别注意ptr_map

答案 6 :(得分:0)

  1. for vectors no。
  2. 列表是。 怎么样? 迭代器用作指向列表中特定节点的指针。 所以你可以为任何结构分配值,如:

    列出mylist;

    一对&LT; list :: iterator,int&gt;温度;

    temp = make_pair(mylist.begin(),x);