C++ 复制构造函数以转移唯一\u ptr的所有权

C++ 复制构造函数以转移唯一\u ptr的所有权,c++,copy-constructor,unique-ptr,ownership,C++,Copy Constructor,Unique Ptr,Ownership,我需要编写一个复制构造函数,它还可以转移被复制对象的唯一\u ptr成员的所有权。情况如下: C类{ //C类的东西 }; 甲级{ 公众: 公共A(); 公共A(施工A&A); 私人: std::唯一的ptr c; } B类{ 公众: B(常数A和B):A_uuz(A){} 私人: A A_; }; 我应该如何实现A的复制构造函数 我想你的意图或方法是错误的 复制构造函数旨在创建参数的副本,但由于unique\u ptr维护唯一所有权,因此不能复制它。实际上,您可以使唯一的_ptr成员可变,然

我需要编写一个复制构造函数,它还可以转移被复制对象的唯一\u ptr成员的所有权。情况如下:

C类{
//C类的东西
};
甲级{
公众:
公共A();
公共A(施工A&A);
私人:
std::唯一的ptr c;
}
B类{
公众:
B(常数A和B):A_uuz(A){}
私人:
A A_;
};

我应该如何实现
A
的复制构造函数

我想你的意图或方法是错误的

复制构造函数旨在创建参数的副本,但由于
unique\u ptr
维护唯一所有权,因此不能复制它。实际上,您可以使唯一的_ptr成员
可变,然后在复制构造函数中移动它指向的资源,但这绝对是疯狂的(这就是
std::auto_ptr
所做的,这就是它被弃用的原因)

因此,您需要:

  • 将移动构造函数添加到a和B(+删除复制构造函数)
  • unique_ptr
    切换到
    shared_ptr
    ,但前提是C实际上是要共享的
还有第三个选项,即在a的复制构造函数中复制唯一的\u ptr指向的对象,即:

A::A(const A& a) : c_(std::unique_ptr<C>(a.c_ ? new C(*a.c_) : nullptr)) {
}
A::A(常数A&A):c_(std::unique_ptr(A.c_?new c(*A.c_):nullptr)){
}
从技术上讲

编写一个复制构造函数,该构造函数还可以转移被复制对象的唯一\u ptr成员的所有权

您可以这样做:

class Bad
{
private:
    unique_ptr<int> p_;
public:
    Bad(): p_( new int(666) ) {}
    Bad( Bad& other )
       : p_( move( other.p_ ) )
    {}
};
类错误
{
私人:
独特的;
公众:
Bad():p_(新int(666)){}
坏(坏&其他)
:p_(移动(其他.p_))
{}
};
因为一个复制构造函数也可以有这个签名,再加上两个,除了更传统的
Bad(const Bad&)

我把这个类命名为Bad,因为它真的很糟糕,除了破坏别人的代码之外,做这件事毫无意义

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

  • 实现移动的移动构造函数,或

  • 实现复制的普通复制构造函数,或

  • 将类设计更改为共享所有权


显然,您不能只执行
std::unique\u 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
    ,因此
    c
    的定义将变为:

    std::shared_ptr<C> c_;
    

    现在
    foo
    bar
    指向相同的
    C
    对象,并共享它的所有权。在引用该共享对象的所有
    shared_ptr
    s被删除之前,不会删除该共享对象。

    因此,当您制作副本时,是否要使原始对象无效?我建议删除复制构造函数并使类仅可移动。如果原始对象是指原始对象A,那么它应该是“transferref”,作为类B的成员。你能提供一个例子吗?@Gabrielecswosh花一些时间阅读标签上的问题/答案。我不会认为意图是错误的。创建一个普通类型的接口模型是非常好的,但是包装类型不能自然地暴露出来。我不同意你的观点。您可以复制保存唯一\u ptr的对象。例如,我可以实现LinkedList类,该类将unique_ptr作为下一个元素的指针。这是否意味着我不能或不应该复制喜欢的列表?我可能想复制链表本身,并将该副本保存在所复制链表的唯一\u ptr中object@DavidHaim,但OP希望转移副本构造函数的所有权-这是问题的标题所说的。我认为这是错误的做法。DavidHaim实际上Adam Romanek是正确的,因为我的意图是转移所有权,而不是复制由UnQuyjpTR指向的对象。我可以为这个例子问一个移动构造函数的例子吗?@Gabrielecswosh,这里有:。请注意,当您将仅移动类型作为成员时,编译器默认为您生成相同的代码,例如unique_ptr:(注意a中没有复制/移动构造函数,它仍按预期工作)
    A foo;
    A bar(foo);