传递 unique_ptr<T> 的 C++ 向量而不传递所有权
Pass C++ vector of unique_ptr<T> without passing ownership
我有一个 class Outer
,其中包含一个 Inner
成员和 拥有 一个 unique_ptr 元素的向量:
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 个元素的向量,并将所有权转移到它自己的向量 class 成员:
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()
,否则编译器会抱怨我试图在每个向量元素上调用已删除的函数(可能是复制构造函数)。
我有一个非法的内存访问,我相信这是因为两个 class 都认为他们拥有矢量元素并且一个试图删除一个已经删除的 Element
.
如何让 Outer
拥有内存并将元素传递给 Inner
使用(不取得所有权)?
如果 Inner 应该访问相同的向量但不拥有它,为什么不让 Inner 保留对 Outer 中的向量的引用,因为它们具有相同的生命周期?
class Inner
{
public:
Inner(Elements& vec):_vec(vec) {}
~Inner() = default;
private:
Elements& _vec; // This is a reference to vector of unique_ptr, no ownership
};
不能有两个 std::unique_ptr
指向同一个对象。 unique_ptr
意味着 唯一 所有权。
如果您需要共享所有权,请改用 std::shared_ptr
s。在您的示例中,它应该是 drop-in 替换,只需更改 using
声明:
using Elements = std::vector<std::shared_ptr<Element>>;
如果您不希望 Inner
对象拥有其 _vec
成员指向的对象,那么它应该是原始指针的向量:
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;
};
当然,这样做意味着如果 Outer
释放它拥有的任何 Element
元素,那么您 运行 将面临让 _vec
的元素悬空的风险不更新任何指向它们的 Inner
对象。您可以通过存储指向 Outer
对象的指针而不是直接存储指向 Element
对象的指针来部分减轻这种风险:
class Outer
{
void call()
{
_inner.aMethod(this);
}
//...
};
class Inner
{
// ...
void aMethod(Outer* outer)
{
outer_ = outer;
}
private:
Outer* outer_;
};
Inner
将仅通过 Outer
对象访问其 Element
(您可以使 Inner
成为 Outer
的 friend
如有必要)。这仍然存在 Inner
对象可能比它指向的 Outer
对象更长寿的可能性,但它确实在一定程度上降低了风险。
我有一个 class Outer
,其中包含一个 Inner
成员和 拥有 一个 unique_ptr 元素的向量:
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 个元素的向量,并将所有权转移到它自己的向量 class 成员:
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()
,否则编译器会抱怨我试图在每个向量元素上调用已删除的函数(可能是复制构造函数)。
我有一个非法的内存访问,我相信这是因为两个 class 都认为他们拥有矢量元素并且一个试图删除一个已经删除的 Element
.
如何让 Outer
拥有内存并将元素传递给 Inner
使用(不取得所有权)?
如果 Inner 应该访问相同的向量但不拥有它,为什么不让 Inner 保留对 Outer 中的向量的引用,因为它们具有相同的生命周期?
class Inner
{
public:
Inner(Elements& vec):_vec(vec) {}
~Inner() = default;
private:
Elements& _vec; // This is a reference to vector of unique_ptr, no ownership
};
不能有两个 std::unique_ptr
指向同一个对象。 unique_ptr
意味着 唯一 所有权。
如果您需要共享所有权,请改用 std::shared_ptr
s。在您的示例中,它应该是 drop-in 替换,只需更改 using
声明:
using Elements = std::vector<std::shared_ptr<Element>>;
如果您不希望 Inner
对象拥有其 _vec
成员指向的对象,那么它应该是原始指针的向量:
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;
};
当然,这样做意味着如果 Outer
释放它拥有的任何 Element
元素,那么您 运行 将面临让 _vec
的元素悬空的风险不更新任何指向它们的 Inner
对象。您可以通过存储指向 Outer
对象的指针而不是直接存储指向 Element
对象的指针来部分减轻这种风险:
class Outer
{
void call()
{
_inner.aMethod(this);
}
//...
};
class Inner
{
// ...
void aMethod(Outer* outer)
{
outer_ = outer;
}
private:
Outer* outer_;
};
Inner
将仅通过 Outer
对象访问其 Element
(您可以使 Inner
成为 Outer
的 friend
如有必要)。这仍然存在 Inner
对象可能比它指向的 Outer
对象更长寿的可能性,但它确实在一定程度上降低了风险。