指向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
- 对于矢量没有。
- 列表是的。怎么样?迭代器用作指向列表中特定节点的指针。所以你可以为任何结构分配值,如: 列表mylist; pair <list :: iterator,int> temp; temp = make_pair(mylist.begin(),x);
以上是关于指向std :: vector和std :: list元素的指针的主要内容,如果未能解决你的问题,请参考以下文章
我是不是保证在移动向量后指向 std::vector 元素的指针有效?