传递unique_ptr< T>的C ++向量没有通过所有权 [英] Pass C++ vector of unique_ptr<T> without passing ownership
问题描述
我有一个外部
类,其中包含一个 Inner
成员和 owns 一个unique_ptr元素的向量:
I have a class Outer
which contains an Inner
member and owns a vector of unique_ptr elements:
using Elements = std::vector<std::unique_ptr<Element>>;
class Outer
{
void call()
{
_inner.aMethod(_vec);
}
Inner _inner;
Elements _vec; // This should remain the owner of each Element
};
Inner
接收unique_ptr元素的向量,并将所有权转移给它自己的向量类成员:
Inner
receives the vector of unique_ptr elements and it transfers ownership to it's own vector class member:
class Inner
{
public:
Inner() = default;
~Inner() = default;
void aMethod(Elements& vec)
{
_vec = std::move(vec);
}
private:
Elements _vec; // This is a vector of unique_ptr but I don't want this class to own the memory
};
我愚蠢地使用了 std :: move()
,因为否则编译器会抱怨我试图在每个矢量元素上调用一个已删除的函数(可能是复制构造函数).
I stupidly used std::move()
because otherwise the compiler complained I was trying to call a deleted function (probably the copy constructor) on each vector element.
我有一个非法的内存访问权限,我相信是因为两个类都认为它们拥有向量元素,并且一个试图删除已经删除的 Element
.
I have an illegal memory access and I believe it is because both classes think they own the vector elements and one has tried to delete an already-deleted Element
.
我如何让外部
拥有内存,然后将元素传递给 Inner
来使用(不获取所有权)?
How do I have Outer
owning the memory and just pass the elements to Inner
to use (not take ownership)?
推荐答案
您不能有两个 std :: unique_ptr
指向同一对象. unique_ptr
表示 unique 所有权.
You cannot have two std::unique_ptr
s pointing to the same object. unique_ptr
implies unique ownership.
如果您需要共享所有权,请改用 std :: shared_ptr
s.在您的示例中,它应该是直接替换,只需更改 using
声明:
If you need ownership to be shared, use std::shared_ptr
s instead. In your example, it should be a drop-in replacement, just change the using
declaration:
using Elements = std::vector<std::shared_ptr<Element>>;
如果您不希望 Inner
对象拥有其 _vec
成员指向的对象,则它应该是原始指针的向量:
If you don't want Inner
objects to own the objects pointed to by its _vec
member, then it should be a vector of raw pointers:
class Outer
{
void call()
{
std::vector<Element*> observer;
std::transform(_vec.begin(), _vec.end(), std::back_inserter(observer),
[](std::unique_ptr<Element>& el) { return el.get(); });
_inner.aMethod(observer);
}
//...
};
class Inner
{
// ...
void aMethod(std::vector<Element*> vec)
{
_vec = std::move(vec);
}
private:
std::vector<Element*> _vec;
};
当然,这样做意味着如果 Out
释放了任何 Element
,则冒着使 _vec
元素悬空的风险.拥有它,而无需更新指向它们的任何 Inner
对象.您可以通过存储指向 Outer
对象的指针而不是直接存储指向 Element
s的指针来部分缓解这种风险:
Of course, doing this would mean that you run the risk of leaving _vec
's elements dangling if Outer
frees any of the Element
s it owns without updating any Inner
objects that are pointing to them. You could partially mitigate that risk by storing a pointer to the Outer
object instead of storing pointers directly to the Element
s:
class Outer
{
void call()
{
_inner.aMethod(this);
}
//...
};
class Inner
{
// ...
void aMethod(Outer* outer)
{
outer_ = outer;
}
private:
Outer* outer_;
};
然后,
Inner
只能通过 Outer
对象访问其 Element
(您可以将 Inner
设置为<外部
的code> friend (如有必要).仍然有可能使 Inner
对象超过其指向的 Outer
对象,但是确实降低了风险.
Inner
would then only access its Element
s via the Outer
object (you could make Inner
a friend
of Outer
if necessary). This still leaves the possibility that an Inner
object could outlive the Outer
object it points to, but it does reduce the risk somewhat.
这篇关于传递unique_ptr< T>的C ++向量没有通过所有权的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!