C++ 为什么插入用户定义的析构函数需要用户定义的复制构造函数

C++ 为什么插入用户定义的析构函数需要用户定义的复制构造函数,c++,c++11,destructor,copy-constructor,unique-ptr,C++,C++11,Destructor,Copy Constructor,Unique Ptr,编译以下代码: #include <vector> #include <iostream> #include <memory> using namespace std; class container { public: container(){} ~container(){} }; class Ship { public: Ship(){} //Ship(const Ship & other){cout<&

编译以下代码:

#include <vector>
#include <iostream>
#include <memory>

using namespace std;

class container
{
public:
    container(){}
    ~container(){}
};

class Ship
{
public:
    Ship(){}
    //Ship(const Ship & other){cout<<"COPY"<<endl;}
    //~Ship(){}

    std::unique_ptr<container> up;
};

Ship buildShip()
{
    Ship tmp;
    return tmp;
}

int main(int argc, char *argv[])
{
    return 0;
}
汇编:

Ship(){}
//Ship(const Ship & other){cout<<"COPY"<<endl;}
//~Ship(){}
Ship(){}
Ship(const Ship & other){cout<<"COPY"<<endl;}
~Ship(){}
Ship(){}

船舶(施工船舶和其他){cout这个想法是,如果编译器生成的析构函数对您的类不够好,那么复制构造函数和复制赋值运算符也可能不够好,因此编译器可能会删除这些复制操作的隐式实现。从技术上讲,编译器甚至可能会给您隐式复制操作如果您有一个用户定义的析构函数,但这种行为在c++11中是不推荐的

好的,您仍然需要一个复制构造函数,因为
buildShip()
按值返回


(然而,有趣的是,您能够编译使用隐式复制构造函数的版本。您不应该能够这样做,因为
唯一的\u ptr
成员…

编译代码是因为
buildShip()
将在返回
tmp
时使用编译器自动生成的移动构造函数。添加用户声明的析构函数会阻止编译器自动生成析构函数。例如,see或questions。由于成员
up
std::unique\u ptr和
unique\u ptr
的复制构造函数被显式删除

这将编译,因为编译器被显式要求生成移动构造函数:

class Ship
{
public:
    Ship(){}
    Ship(Ship&&) = default;
    ~Ship(){}
    std::unique_ptr<container> up;
};
级船舶
{
公众:
Ship(){}
Ship(Ship&)=默认值;
~Ship(){}
std::唯一的ptr up;
};

-clang 3.9.1在这里的行为与clang:Error相同:source_file.cpp:27:12:错误:调用“Ship”的隐式删除复制构造函数返回tmp;…是的,所有4个编译器都说在定义析构函数时隐式删除了复制构造函数这是由于
unique\u ptr
unique\u ptr
无法复制,因此隐式复制构造函数被声明为deleted。您是谁afaik:buildShip返回值并不意味着需要显式复制构造函数。这不是特例,它与其他任何东西都是一样的,隐式构造函数可能好,也可能不好,但这并不取决于buildShip。它确实使用复制构造函数,但不一定需要显式构造函数。只是为了确保理解它:包括用户定义的析构函数可以防止编译器自动生成移动运算符。由于缺少移动运算符,buildShip函数的返回将尝试复制tmp Ship,从而调用默认的复制构造函数,然后复制tmp,从而复制唯一的_ptr,从而产生错误。对吗es,行
return tmp;
尝试使用
Ship
的副本,由于
unique_ptr
成员,该副本已被明确删除。再次感谢@AMA伟大的回答!就像您已经为我的上一次访问提供的一样。
class Ship
{
public:
    Ship(){}
    Ship(Ship&&) = default;
    ~Ship(){}
    std::unique_ptr<container> up;
};