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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了指向std :: vector和std :: list元素的指针相关的知识,希望对你有一定的参考价值。

我有一个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

答案

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

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

另一答案

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

另一答案

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

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

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

另一答案

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

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

另一答案

只需使它们都存储指针,在不需要它们时显式删除它们。

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
另一答案

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

特别是,看看ptr_map

另一答案
  1. 对于矢量没有。
  2. 列表是的。怎么样?迭代器用作指向列表中特定节点的指针。所以你可以为任何结构分配值,如: 列表mylist; pair <list :: iterator,int> temp; temp = make_pair(mylist.begin(),x);

以上是关于指向std :: vector和std :: list元素的指针的主要内容,如果未能解决你的问题,请参考以下文章

指向 std::vector 的指针,指针声明

我是不是保证在移动向量后指向 std::vector 元素的指针有效?

指向基类的指针的 std::vector 的深拷贝

迭代时在 std::vector 中保存指向不同类型的指针

在基于范围的 for 循环中从 std::vector<Object> 获取指向 Object 的指针

从原始数据就地创建 std::vector