【发布时间】:2021-03-04 10:47:43
【问题描述】:
假设我们有一个存储一些数据的结构或类:
struct Foo
{
int bar;
}
还假设我想存储两个单独的向量;一个包含Foo 的实际实例和shared_ptr 的向量,这将允许我任意访问该数据:
std::vector<Foo> data; // Where the data actually is
std::vector<std::shared_ptr<Foo>> ptr_data; // A set of pointers to the elements in data
如何将一个元素插入到 data 向量中,然后添加一个指向该元素的相应 shared_ptr? 我希望实际数据的唯一副本存在于data 向量。
我不相信我可以使用make_shared,因为我似乎找不到任何关于如何控制数据存储位置的文档。并且不应该在函数超出范围时收集匿名数据吗?
void addDataToVectors()
{
ptr_data.push_back(std::make_shared<Foo>( 20 )); // Can I put this into the data vector?
// And shouldn't the data disappear as soon as this function ends?
}
我也试过这个:
void addDataToVectors()
{
data.push_back({ 20 }); // Add the instance to data
// Attempt to create a shared pointer from the last address in data
ptr_data.push_back(std::shared_ptr<Foo>(&data.back()));
}
但这似乎不起作用。添加第一组数据及其指针是正确的,但ptr_data 向量中的每个后续push_back 似乎都会破坏除最后一个之外的所有条目。这种方法显然有问题,开始时感觉很糟糕。
对 STL 容器执行此操作的正确方法是什么?
【问题讨论】:
-
没有合适的方法来做这样的事情。
std::vector和std::shared_ptr都不会按照您认为的方式工作。 shared_ptr 不指向存储在任何其他容器中的任何对象。 shared_ptr 存在的全部原因是它拥有对象,并且完全负责删除它。容器的全部原因是做同样的事情,但方式不同。除此之外,向量可以重新分配和移动它们的内容,这是一个完全不合逻辑的情况。选择一个,容器或 shared_ptr,但不能同时选择两者。 -
您可以拥有两个指向相同对象的共享指针容器,也可以拥有两个指向相同容器对象的共享指针。
-
一个对象只能有一个所有者(或共享所有者),因此当它的所有者被删除时,它只会被删除一次。容器拥有它们的对象,因此您不能将这些相同的对象赋予另一个所有者。你可以使用原始指针向量吗?只要您可以保证在对象向量被销毁后永远不会使用原始指针,那就没问题了。此外,您不能更改整数向量的内容,因为这会使您的原始指针无效。
-
如果您使用
shared_ptrs,那么两个向量都需要包含shared_ptrs 到相同的Foos。如果您使用原始指针,那么每次添加Foo时都需要检查向量是否重新分配,如果确实如此,请重建原始指针向量。 -
另一种方法是忘记指针并将索引存储为
std::vector<std::size_t> idx_data;
标签: c++ stl c++14 smart-pointers