为什么 std::make_unique<A>(*this) 可以调用 A 的隐式声明的复制构造函数

wss*_*one 0 c++ constructor implicit

源问题来自Usage of this* in make_unique

代码如下,最佳答案是:

在 中clone()*this是对 的左值引用,因此您正在从 (对的左值引用) (在 内部)A构造 a ,因此您正在使用 的隐式声明的复制构造函数:AAstd::make_uniqueA

A(A const&);
Run Code Online (Sandbox Code Playgroud)

我很困惑类A有一个虚拟析构函数virtual ~A(){},编译器将不再生成复制构造函数。那么为什么std::make_unique<A>(*this)可以调用 的隐式声明的复制构造函数呢A

class Base {
    public:
        virtual ~Base() {}
        virtual std::unique_ptr<Base> clone() = 0;
        virtual void print() = 0;
};

class A: public Base {
        std::string name_;
    public:
        A(std::string name ){name_ = name;};
        std::unique_ptr<Base> clone() override{
            return std::make_unique<A>(*this);
        };
        void print( ) override{
            std::cout << "Class A: " << name_;    
        };
        virtual ~A(){};
};

class Factory{
        std::unique_ptr<A> type = std::make_unique<A>("MyName");  
    public:
        std::unique_ptr<Base> createInstance(){
            return type->clone();
    }
};

int main(){
    Factory factory;
    auto instance = factory.createInstance();
    instance->print();
}
Run Code Online (Sandbox Code Playgroud)

我们都知道C++类定义析构函数的规则,编译器不会生成默认的复制构造函数和重载赋值运算符,而这两者的移动版本,看class中的定义A,它定义了virtual ~A(){},所以不会有隐式的要调用的复制构造函数std::make_unique<A>(*this)

use*_*522 5

我们都知道c++类定义析构函数的规则,编译器不会生成默认的复制构造函数和重载赋值运算符,

这是不正确的。无论用户声明的析构函数如何,编译器都会声明并定义隐式复制操作。

然而,自 C++11 以来,此行为已被弃用。尽管如此,它并没有从语言中删除(而且我预计它不会很快被删除)。因此,您最多可以期望编译器警告您有关已弃用的行为(例如 Clang 的 with -Wdeprecated),但目前它仍然必须使用隐式复制操作来编译程序。(当然,您可以在 Clang 中将-Wdeprecated警告设置为错误,其他编译器可能有类似的选项。)-Werror=deprecated

这也是为什么遵循 0/3/5 规则如此重要。编译器仍会隐式生成复制操作,即使它们对于具有用户声明的析构函数的类型可能无法正确运行。因此,当您有用户声明的析构函数时,您应该手动定义复制(和移动)操作,或者将它们定义为已删除(如果复制不可能)。