C++ 使用std容器的稳定内存地址(如向量、列表、队列等)

C++ 使用std容器的稳定内存地址(如向量、列表、队列等),c++,pointers,c++11,vector,C++,Pointers,C++11,Vector,注意:我没有意识到指针应该被视为迭代器,因此有人可能会认为我所说的内存地址不稳定应该被称为迭代器失效。请阅读副本,了解我问题的更抽象、更合理的版本 我的问题与此相关: 我想处理一组对象,为了简单起见,这些对象在内存中只存在一次。因此,我想使用一个容器,比如std::vector,一次性存储所有对象。然后我将使用指向其他结构中的对象的指针。不幸的是,std::vector可能会更改其元素的内存地址,因此使用指向这些元素的指针是定义错误的。我需要指针,因为我想使用其他结构引用这些对象,比如std::

注意:我没有意识到指针应该被视为迭代器,因此有人可能会认为我所说的内存地址不稳定应该被称为迭代器失效。请阅读副本,了解我问题的更抽象、更合理的版本

我的问题与此相关:

我想处理一组对象,为了简单起见,这些对象在内存中只存在一次。因此,我想使用一个容器,比如std::vector,一次性存储所有对象。然后我将使用指向其他结构中的对象的指针。不幸的是,std::vector可能会更改其元素的内存地址,因此使用指向这些元素的指针是定义错误的。我需要指针,因为我想使用其他结构引用这些对象,比如std::priority_queue或其他std数据结构

在特定情况下,对象是图形算法中连接的标签,这意味着它们是在整个算法中创建的,因此不能预先分配。这意味着std::vector是不够的,因为它可能会重新定位其内容,使指向这些标签的指针失效,这些标签可能存在于std::priority_队列或其他数据结构中

然而,我需要标签的唯一时刻,是当它们被创建时,或者当我可以从包含数据结构以外的数据结构访问它们时。因此,我不需要从容器中获取第n个元素,我只需要能够将对象保留在堆栈或堆上,并在创建对象时获取指针,以便在其他结构中使用它。最后,当容器从堆栈中弹出时,需要很好地清理其中的元素。我认为std::list可能是合适的,因为我对抽象链表的了解永远不需要重新分配;允许使用稳定的指针

然而,我在任何地方都找不到这种指针稳定性对于std::list是正确的。也许有更好的东西,一些容器类,正是我想要的。当然,我总是可以使用new,将所有指针追加到std::list,并在最后进行delete迭代。但这不是我喜欢的方式,因为它需要更多的内存管理,因为我认为这应该是获得稳定指针所需要的

问题:std::list指针是否稳定?有比std::list更好的解决方案吗

为了说明这个问题,我还举了这个例子:。用std::vector替换std::list,行为将变得未定义

#包括
#包括
#包括
#包括
结构Foo{
Foo(int_a):a(_a){
INTA;
};
结构比较器{
bool操作符()(Foo*a,Foo*b){返回a->aa;}
};
int main(){
std::列出foos;
//std::vector foos;//改用时,行为将变得未定义
std::优先级队列pq;
//在其他结构处理对象时,模拟对象的创建和“包含”。

对于(int i=0;i所有标准容器都有指针/引用和迭代器无效的特定规则。如果您可以预测最大容量,甚至
std::vector
,也可以选择:

  • std::vector
    末尾添加/删除对象可以保持指针和迭代器的稳定,除非
    std::vector
    需要重新分配其内部结构。也就是说,指针和迭代器只有在添加对象且
    v.size()==v.capacity()
    时才会失效。您可以使用
    v.reserve(n)
    以保留空间
  • std::deque
    的两端添加/删除对象可以保持指针稳定,但会使迭代器无效
  • std::list
    中的任意位置添加/删除对象可以保持指针和迭代器的稳定
显然,指向已删除对象的指针和迭代器在任何情况下都是无效的。然而,指向其他对象的指针和迭代器遵循上述规则

操作和内存的开销按容器显示的顺序增加。也就是说,理想情况下,您应该使用
std::vector
,并提前分配足够的内存以保持对象稳定。如果您无法预测所需的最大大小,
std::deque
是次优选项:
std::deque
是一个修复数组ED大小的数组,即每个对象开销相对较小,内存分配相对较少。只有当您需要同时保存指针和迭代器表时,不能预测容器的大小,<代码> STD::清单< /C>是一个合理的选择。为了降低每个对象开销,您可以考虑使用<代码> STD::它与std::list具有相同的失效约束,但只能在一个方向上遍历,使用起来更不方便


< P> >我使用一个<代码> STD::向量有足够的保留内存。如果我不能,我就可以使用一个<代码> STD:vector < /代码>。只有这是真的不可能的时候,我才会考虑使用<代码> STD::DeQue/代码>来存储对象……而且我很少使用<代码> STD::List< <代码>,因为几乎没有任何理由使用它。

< P>是的,在插入列表不会使任何迭代器失效(指针是迭代器),删除元素只会使表示该元素的迭代器失效

cpluplus.com对标准容器的每个成员函数都有迭代器有效性部分,例如:。这些声明通常基于标准,但如果您有疑问,可以进行检查。标准以如下形式声明成员函数的保证:“效果:…不影响迭代器和引用的有效性。”在
std::list
@Yakk之前,考虑
std::deque
std::vector
,它们的指针稳定吗?std::list是否稳定?不仅在实践中,而且在定义它们的行为时也是如此。您更喜欢哪一个作为容器