为什么插入用户定义的析构函数需要用户定义的复制构造函数
Why does the insertion of user defined destructor require an user defined copy constructor
编译以下代码:
#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(const Ship & other){cout<<"COPY"<<endl;}
//~Ship(){}
编译:
Ship(){}
Ship(const Ship & other){cout<<"COPY"<<endl;}
~Ship(){}
不编译:
Ship(){}
//Ship(const Ship & other){cout<<"COPY"<<endl;}
~Ship(){}
为什么插入用户定义的析构函数需要一个用户定义的复制构造函数,为什么我们在上面的例子中根本需要一个复制构造函数?
我希望上面的示例中不需要复制构造函数,因为 unique_ptr 甚至无法复制。
想法是,如果编译器生成的析构函数对您的 class 来说不够好,那么复制构造函数和复制赋值运算符也可能不够好,因此编译器 可能删除那些复制操作的隐式实现。从技术上讲,即使您有用户定义的析构函数,编译器仍可能为您提供隐式复制操作,但这种行为在 c++11 中已被弃用。
AFAIK,您仍然需要一个复制构造函数,因为 buildShip()
returns 按值计算。
(但是,有趣的是您能够编译使用隐式复制构造函数的版本。由于 unique_ptr
成员,您不应该这样做...)
代码被编译是因为 buildShip()
会在返回 tmp
时使用编译器自动生成的移动构造函数。添加用户声明的析构函数可防止编译器自动生成析构函数。例如,参见 or 个问题。并且编译器生成的拷贝构造函数不能使用,因为成员up
是std::unique_ptr
。 unique_ptr
的复制构造函数被显式删除。
所以这将编译,因为明确要求编译器生成移动构造函数:
class Ship
{
public:
Ship(){}
Ship(Ship&&) = default;
~Ship(){}
std::unique_ptr<container> up;
};
编译以下代码:
#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(const Ship & other){cout<<"COPY"<<endl;}
//~Ship(){}
编译:
Ship(){}
Ship(const Ship & other){cout<<"COPY"<<endl;}
~Ship(){}
不编译:
Ship(){}
//Ship(const Ship & other){cout<<"COPY"<<endl;}
~Ship(){}
为什么插入用户定义的析构函数需要一个用户定义的复制构造函数,为什么我们在上面的例子中根本需要一个复制构造函数?
我希望上面的示例中不需要复制构造函数,因为 unique_ptr 甚至无法复制。
想法是,如果编译器生成的析构函数对您的 class 来说不够好,那么复制构造函数和复制赋值运算符也可能不够好,因此编译器 可能删除那些复制操作的隐式实现。从技术上讲,即使您有用户定义的析构函数,编译器仍可能为您提供隐式复制操作,但这种行为在 c++11 中已被弃用。
AFAIK,您仍然需要一个复制构造函数,因为 buildShip()
returns 按值计算。
(但是,有趣的是您能够编译使用隐式复制构造函数的版本。由于 unique_ptr
成员,您不应该这样做...)
代码被编译是因为 buildShip()
会在返回 tmp
时使用编译器自动生成的移动构造函数。添加用户声明的析构函数可防止编译器自动生成析构函数。例如,参见 up
是std::unique_ptr
。 unique_ptr
的复制构造函数被显式删除。
所以这将编译,因为明确要求编译器生成移动构造函数:
class Ship
{
public:
Ship(){}
Ship(Ship&&) = default;
~Ship(){}
std::unique_ptr<container> up;
};