【问题标题】:Alternatives to std::vector due to reallocation that invalidates pointers to elements由于重新分配使指向元素的指针无效,因此替代 std::vector
【发布时间】:2016-02-28 14:23:09
【问题描述】:

这可能是一个新问题(我是),但我已经尽可能多地搜索以找到以下问题的解决方案

我有以下场景(当然是重度提炼):

class Container
{
std::vector<Object> obj;
};

class Pointers
{
std::vector<Object*> obj_ptr;
};

我有一个例程将 Object 类型的元素推回容器中的向量 obj,然后将指向同一元素的指针推回 obj_ptr

总体思路是 obj_ptr[i] == &obj[i] 贯穿程序的整个生命周期。

我遇到的问题是,每当 obj 的容量需要增加时,所有的指针都会失效,使得 obj_ptr 完全没用。我已经使用最大预期大小(大约 10^7)尝试了 obj.reserve() 并使用相同大小初始化向量。问题仍然存在。

不确定它是否重要,但我正在使用 VS 2015 Com。

谢谢!

【问题讨论】:

  • 这听起来像是您这边的设计问题/XY 问题。为什么你一开始会想要拥有这样的第二个向量?例如,如果您需要一种方法来迭代其他对象的指针,请实现自定义迭代器。如果要实现一个将对象暴露为指针的接口,请在接口的实现中直接访问向量。
  • 嗨塞巴斯蒂安。这是以下问题的提炼版本 本例中的容器是一个 mesh,它具有 pointsedgesfaces 基本上,每个点、边和面都需要知道它属于哪个mesh,以及它的相邻pointedge是哪个, face 元素,以便可以应用某种算法来修改几何形状。所以为了避免重复,只有 mesh 包含 vector>vectorvector。对于其他每一种类型,邻接列表都存储在指针向量中。
  • 只需使用索引而不是指针,您的问题就会消失。

标签: c++ pointers visual-studio-2015 stdvector


【解决方案1】:

常见的替代方法是使用smart pointers like

class Container {
    std::vector<std::unique_ptr<Object>> obj;
};

class Container {
    std::vector<std::shared_ptr<Object>> obj;
};

取决于您的用例(语义上)。

【讨论】:

  • 嗯,不,即使是智能指针也不知道原来的向量被重新分配了。
  • @PeteBecker:但是obj[i]-&gt;get() == obj_ptr[i] 在重新分配后仍然是真的。我认为这就是答案的重点。
  • 谢谢。 shared_ptr 效果很好。干杯!
  • 哦,我明白了:您将智能指针放入另一个容器中。叹。对我来说太复杂了...
  • 对愚蠢的编辑感到抱歉;我必须这样做才能解开问题,这样我才能取消我的反对票。
【解决方案2】:

Boost stable vector 就是为此而设计的。它是一个不会使其值无效的向量(在 O(1) 中访问等)。它符合标准 C++ 容器 API/语义。

它类似于std::vector&lt;std::unique_ptr&lt;T&gt;&gt;,但对你隐藏了智能指针。

【讨论】:

  • 感谢您的建议。主要缺点是它不标准。
  • @AdlA,它不在标准库中,是的。如果你不想依赖第三方库,你可以通过包装 std::vector<:unique_ptr>> 来滚动你自己的实现。
  • 包装std::vector&lt;std::shared_ptr&lt;T&gt;&gt; 是一个有趣的选项,只是为了让它稍微不那么冗长。另外,我只需要添加和读取元素(没有弹出、删除),所以它可能“更安全”。干杯!
【解决方案3】:

可以在Container中使用std::liststd::forward_list,这样指针就不会失效。

class Container
{
std::forward_list<Object> obj;
};

class Pointers
{
std::vector<Object*> obj_ptr;
};

不过,请注意从obj 中删除元素的过程。从obj 中删除一个元素确实使obj_ptr 中的相应指针无效。

【讨论】:

  • 当然,这样还是要多加小心
  • @M.M:嗯...是的:)
【解决方案4】:

你有很多选择

  • 使用像 std::liststd::deque 这样的数据结构,其中添加元素不会使指向预先添加的元素的指针无效。

  • 在第二个数组中保留索引而不是指针

  • 只有指针向量——也许std::vector&lt;std::unique_ptr&lt;Object&gt;&gt; 用于第一个数组,std::vector&lt;Object *&gt; 用于其他数组,或者std::vector&lt;std::shared_ptr&lt;Object&gt;&gt; 用于所有数组。

哪个最有意义取决于您实际尝试做什么。

【讨论】:

  • 谢谢,所有这些建议似乎都是有效的。就我而言,我认为最好的是std::vector&lt;std::shared_ptr&lt;Object&gt;&gt;。干杯!
猜你喜欢
  • 2011-03-18
  • 2015-04-26
  • 2016-02-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-08
  • 1970-01-01
相关资源
最近更新 更多