C++ 自动克隆唯一\u ptr

C++ 自动克隆唯一\u ptr,c++,c++11,clone,copy-constructor,unique-ptr,C++,C++11,Clone,Copy Constructor,Unique Ptr,std::unique_ptr有一个已删除的副本构造函数,这意味着如果您在类Foo中有一个unique_ptr作为数据成员,那么您必须为Foo编写自己的副本构造函数,并手动深度复制该成员(即使编译器生成的复制构造函数对所有其他成员都适用) 为了能够以多态方式进行复制,可以使用clone()方法模式。假设我们的对象有这样一个克隆方法: class Base { virtual std::unique_ptr<Base> clone() = 0; }; 现在,如果我们使用它,我

std::unique_ptr
有一个已删除的副本构造函数,这意味着如果您在类
Foo
中有一个
unique_ptr
作为数据成员,那么您必须为
Foo
编写自己的副本构造函数,并手动深度复制该成员(即使编译器生成的复制构造函数对所有其他成员都适用)

为了能够以多态方式进行复制,可以使用
clone()
方法模式。假设我们的对象有这样一个克隆方法:

class Base {
    virtual std::unique_ptr<Base> clone() = 0;
};
现在,如果我们使用它,我们不需要定义自己的复制构造函数:

class Foo2 {
public:
    ...

private:
    auto_cloned_unique_ptr<Base> b;
    //10 more data members

};
class-Foo2{
公众:
...
私人:
自动克隆\u唯一\u ptr b;
//再增加10名数据成员
};

这样一种方法是否非常不受欢迎(因为在
unique\u ptr
上使用非标准包装器)?

这种方法很好,但您应该非常小心,不要在无意中克隆对象


同样,从unique\u ptr继承可能会提高性能。您的方法的问题是它正在改变unique\u ptr的含义。unique\u ptr的关键是它告诉谁是对象的所有者。如果您为unique\u ptr添加复制构造函数,这意味着什么?您正在复制所有权吗?a和B都是唯一的仅拥有该对象?这没有意义。如果它们共享所有权,那么您应该使用共享的\u ptr来表示共享所有权。如果您想要拥有该对象副本的唯一所有者,您自然会通过make_unique(*pFoo)来表示。对于基对象和派生对象,使基对象具有
虚拟唯一克隆()常量=0;
是一个完全正常的构造。也就是说,派生类知道如何复制自己,因此它们不会生成切片副本,但它们会向基类返回一个唯一的\u ptr,以指示您将拥有它们生成的副本。在这些克隆操作中,是的,您需要显式处理派生类的不可复制成员,因此,您不能仅使用默认或生成的复制构造函数。您需要回答“复制包含无法复制的内容的内容意味着什么?”

作为一个具体的例子,复制一个具有互斥锁的派生类意味着什么?如果它被锁定,而另一个线程正在等待它呢?看看为什么很难给出一个一般性的答案?

让我首先解释一下您想做的事情:您希望
Foo
的每个实例在
b
中都有自己的
Base
实例;特别是,如果您复制
Foo
,则副本将有自己的新
Base
,最初具有相同的“值”。换句话说,
Base
的行为应类似于值

同时,您不能将
Base
直接存储在
Foo
中,因为它是一个抽象类。换句话说,您希望
b
具有
多态性

这就是你想要的:你想要一个多态值。其他人已经认识到这一需要,并建议将C++20作为。从文档中:

类模板,多态性_值,将类似值的语义赋予 自由存储分配的对象。多态_值可能包含 对象,并复制 多态_值将复制派生类型的对象


它有一个参考实现,您现在就可以使用。简单地说,它是一个类似于您提议的
std::unique_ptr
的包装器。

有很多这样的提议。搜索
value_ptr
,仅举一个例子。一般来说,很难保证正确使用它,因此它不太合适感觉自己属于标准是正确的。顺便问一下,为什么不从
unique\ptr
继承
private
并使用构造函数继承呢?“这种方法非常不受欢迎吗?”是一个更适合IMO的问题。你可能对Shean Parent解决这个问题的方法感兴趣。他在不同场合的演讲中提出了他的解决方案,例如:@dau_sama这是关于需要深度复制语义的问题。例如,你将多态成员变量x,y保留在类a中,当encompassing对象A被复制。我希望在不为A编写自定义复制构造函数的情况下自动执行此操作。相反,应该将成员x和y包装到智能指针中,该指针可以按正确的(最具体的)深度复制对象复制继承层次结构中的构造函数。如果您想更好地了解用例,请查阅
value\u ptr
。在这种情况下,从
unique\u ptr
继承将不会有帮助,因为它没有空基优化(它从来都不是空类)
template <typename T>
class auto_cloned_unique_ptr
{
private:
    std::unique_ptr<T> up;

public:
    // copy constructor
    auto_cloned_unique_ptr(auto_cloned_unique_ptr<T> const& other)
        : up(other.up->clone()) {}

    // copy assignment
    auto_cloned_unique_ptr<T>& operator =(auto_cloned_unique_ptr<T> const& other)
    {
        this->up = other.up->clone();
        return *this;
    }

    auto_cloned_unique_ptr(std::unique_ptr<T> _up)
        : up(std::move(_up)) {}

    // Delegate everything else to unique_ptr
    auto_cloned_unique_ptr(auto_cloned_unique_ptr<T>&& other)
        : up(std::move(other.up)) {}

    auto_cloned_unique_ptr<T>& operator =(auto_cloned_unique_ptr<T>&& other)
    {
        this->up = std::move(other.up);
        return *this;
    }

    auto operator *() const {return *up;}
    auto operator->() const {return up.operator->();}
    auto get() -> const {return up.get();}

};
class Foo2 {
public:
    ...

private:
    auto_cloned_unique_ptr<Base> b;
    //10 more data members

};