我需要编写一个复制构造函数,它还传递被复制对象的unique_ptr成员的所有权。情况如下:
class C{
// C class stuff
};
class A{
public:
public A();
public A(const A& a);
private:
std::unique_ptr<C> c_;
}
class B{
public:
B(const A& b) : a_(a){}
private:
A a_;
};
我应该如何为A
实现复制构造函数?
答案 0 :(得分:6)
我猜你的意图或做法是错误的。
复制构造函数用于创建参数的副本,但由于unique_ptr
维护唯一所有权,因此无法复制它。您可以实际上创建unique_ptr成员mutable
,然后将其指向的资源移动到复制构造函数中,但这绝对是疯狂的(这是std::auto_ptr
所做的事情。这就是它被弃用的原因。
因此,您需要:
unique_ptr
切换到shared_ptr
,但前提是C实际上是要共享还有第三种选择,即在A的复制构造函数中复制由unique_ptr指向的对象,即:
A::A(const A& a) : c_(std::unique_ptr<C>(a.c_ ? new C(*a.c_) : nullptr)) {
}
答案 1 :(得分:4)
显然,您不能只删除std::unique_ptr
s,因为它们的赋值运算符已被删除。这是为了迫使程序员定义他想要的行为。
c_
的所有权,使原始项目无效。c_
,保留原始项目的有效性。c_
的所有权,以便新项目和原始项目都引用同一个对象。在案例1 中,您正在寻找的是移动构造函数,默认移动构造函数将正常工作。所以你不需要编写任何代码,你可以这样做:
A temp;
A foo(std::move(temp));
请注意temp
移动后无效。
在案例2 中,您需要向A
添加自定义复制构造函数,以创建原始c_
的副本:
A(const A& a):c_(new C(*(a.c_))){}
在A
中定义后,您可以执行以下操作:
A foo(A());
请注意,这取决于C
的复制构造函数是否正常运行。
在案例3 中,您需要从使用A
到使用std::unique_ptr
从根本上改变std::shared_ptr
,因此{{1}的定义1}}将成为:
c_
std::shared_ptr<C> c_;
的构建方式与c_
std::unique_ptr
版c_
的用法相同。所以只需使用您可以执行的默认实现:
A foo;
A bar(foo);
现在foo
和bar
指向同一个C
对象,并分享对象的所有权。在所有引用它的shared_ptr
被删除之前,不会删除此共享对象。
答案 2 :(得分:3)
技术上,
“编写一个复制构造函数,该构造函数还传输正在复制的对象的unique_ptr成员的所有权
你可以这样做:
class Bad
{
private:
unique_ptr<int> p_;
public:
Bad(): p_( new int(666) ) {}
Bad( Bad& other )
: p_( move( other.p_ ) )
{}
};
因为除了更传统的Bad( const Bad& )
之外,复制构造函数还可以包含此签名以及另外两个签名。
我将该类命名为Bad
,因为它非常糟糕,除了破坏其他人的代码之外,做这件事是没有意义的。
而不是不复制的复制构造函数,
实现移动的移动构造函数,或
实现复制或
将班级设计改为例如共享所有权。