【问题标题】:Using map<int, Foo> instead of vector<Foo> to avoid pointer invalidation使用 map<int, Foo> 而不是 vector<Foo> 来避免指针失效
【发布时间】:2019-07-28 23:03:41
【问题描述】:

假设我有一个类 Foo 和一个容器 vector&lt;Foo&gt; Foos。 我使用的算法严重依赖于指向Foos 元素的指针,并且我还需要动态添加Foos 并访问容器的元素。问题是如果我向向量中添加太多元素,它可能需要重新分配元素,从而使指向这些元素的所有指针无效。那么使用map&lt;int, Foo&gt; 代替vector&lt;Foo&gt; 是否有意义?

【问题讨论】:

  • 一个简短的例子来证明你的问题会很有用。

标签: c++ dictionary vector stl containers


【解决方案1】:

std::deque 与向量具有相似的性能(和随机访问),但不会在插入时使指针无效。

但它确实使删除指针无效。

【讨论】:

    【解决方案2】:

    我会使用std::vector&lt;std::shared_ptr&lt;Foo&gt;&gt;,所以我仍然有一个向量,并且无论它们在向量中的位置如何,我仍然有有效的指针。

    【讨论】:

      【解决方案3】:

      这个答案的重点是如何防止指针失效发生,同时仍然坚持std::vector

      预分配

      如果您事先知道向量可以包含的Foo 对象的最大数量,您可以简单地使用std::vector::reserve() 成员函数重新分配向量的缓冲区。这样,对象的重新分配就不会发生,因此指向Foo 对象的指针也不会失效。

      使用指针向量

      或者,您可以使用std::vector&lt;std::unique_ptr&lt;Foo&gt;&gt; 代替std::vector&lt;Foo&gt;。这样,即使向量重新分配其元素,指向的Foo 对象的地址也不会改变,因为将重新分配的是std:unique_ptr&lt;Foo&gt; 对象,而不是Foo 对象。因此,指向Foo 对象的指针仍然有效。


      后一种方法引入了额外的间接层,因此效率低于前一种。

      【讨论】:

        【解决方案4】:

        你有四种可能:

        • 您使用了非无效容器。这是你的建议。

        • 您事先在向量中保留了足够的空间 (El Professor's answer)。这仅在您提前知道Foos 的最大数量时才有效。

        • 您使用(智能)指针向量 (Michael Chourdakis' answer)。只要您不需要将指针用作迭代器,这就会起作用。

        • 您没有对 vector&lt;Foo&gt; 进行任何更改,但是您可以使用索引而不是指针来使您的算法工作。这允许您查看之前和之后的元素(在检查向量边界之后),并且索引不会因重新分配而失效。

        【讨论】:

          猜你喜欢
          • 2011-12-20
          • 2016-05-16
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-10-03
          • 2012-04-04
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多