复制构造函数以转移 unique_ptr 的所有权

Copy Constructor to transfer ownership of a unique_ptr

我需要编写一个复制构造函数,它还转移被复制对象的 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 的复制构造函数?

我猜你的意图或方法是错误的。

复制构造函数旨在创建参数的 copy,但由于 unique_ptr 保持唯一所有权,因此无法复制它。你 可以 实际上使 unique_ptr 成为成员 mutable 然后将它指向的资源移动到复制构造函数中,但这绝对是疯狂的(这就是std::auto_ptr 确实如此,这就是它被弃用的原因)。

因此您需要:

  • 向 A 和 B 添加移动构造函数(+ 删除复制构造函数)
  • 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)) {
}

从技术上讲,

write a copy constructor that also transfer the ownership of a unique_ptr member of the object being copied

你可以这样做:

class Bad
{
private:
    unique_ptr<int> p_;
public:
    Bad(): p_( new int(666) ) {}
    Bad( Bad& other )
       : p_( move( other.p_ ) )
    {}
};

因为复制构造函数也可以有这个签名,再加上两个,除了更常规的Bad( const Bad& )

我把它命名为 class Bad 因为它真的很糟糕,除了破坏别人的代码外,这样做没有任何意义。

而不是不复制的复制构造函数,

  • 实现移动

  • 的移动构造函数
  • 实现一个复制

  • 的普通复制构造函数
  • 将 class 设计更改为例如共享所有权.

显然,您不能只对 std::unique_ptr 进行赋值,因为它们的赋值运算符已被删除。这是故意强迫程序员定义他想要的行为。

  1. 新项目取得 c_ 的所有权,使原始项目无效。
  2. 新物品复制c_,保留原物品有效期。
  3. 新项目共享 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,因此定义c_ 将变为:

std::shared_ptr<C> c_;

您对 c_ 的构建将与您已经在 std::unique_ptr 版本的 c_ 中使用的相同。因此,只需使用默认实现即可:

A foo;
A bar(foo);

现在 foobar 指向同一个 C 对象,并共享它的所有权。在删除引用它的所有 shared_ptr 之前,不会删除此共享对象。