由于重新分配使指向元素的指针无效,std::vector 的替代方案

Alternatives to std::vector due to reallocation that invalidates pointers to elements

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

我有以下场景(当然是经过大量提炼的):

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

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

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

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

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

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

谢谢!

常见的替代方法是像

一样使用 smart pointers
class Container {
    std::vector<std::unique_ptr<Object>> obj;
};

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

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

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

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

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

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

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

它类似于 std::vector<std::unique_ptr<T>>,但对您隐藏了智能指针。

你有很多选择

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

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

  • 只有指针向量——第一个数组可能是 std::vector<std::unique_ptr<Object>>,其他数组可能是 std::vector<Object *>,或者所有数组可能是 std::vector<std::shared_ptr<Object>>

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