对于不可移动的类型,是否足够(从最佳实践角度来看)?
class A
{
A(const A&) = delete;
A(A&&) = delete;
A& operator=(A) = delete;
public:
A();
};
或者我是否必须单独删除复制/移动赋值运算符?这里还需要一个析构函数吗?
答案 0 :(得分:8)
是的,将复制构造函数和复制赋值运算符声明为deleted
就足够了。由于您要声明复制构造函数和复制赋值运算符,因此不会自动生成移动构造函数和移动赋值运算符。您无需明确声明它们deleted
。
来自§12.8/ 9(强调增加)
如果类X的定义没有明确声明一个移动构造函数,那么当且仅当时,才会隐式声明一个默认 - X没有用户声明的拷贝构造函数,
- X没有用户声明的复制赋值运算符,
- X没有用户声明的移动赋值运算符,
- X没有用户声明的析构函数,以及
- 移动构造函数不会被隐式定义为已删除。
来自§12.8/ 20(强调增加)
如果类X的定义没有明确声明一个移动赋值运算符,那么当且仅当时,才会将其隐式声明为默认值 - X没有用户声明的拷贝构造函数,
- X没有用户声明的移动构造函数,
- X没有用户声明的复制赋值运算符,
- X没有用户声明的析构函数,以及
- 移动赋值运算符不会被隐式定义为已删除。
答案 1 :(得分:3)
根据[class.copy] / 17 operator=(A)
是一个有效的复制赋值运算符,所以是的,声明删除它就足以抑制隐式移动赋值运算符,因此与删除的复制构造函数一起将使类不可复制和不可移动。
你的班级比必要的复杂,但你需要的只是:
class A
{
A(const A&) = delete;
A& operator=(A) = delete;
public:
A();
};
用户声明的复制构造函数禁止隐式移动构造函数,用户声明的复制赋值运算符禁止隐式移动赋值运算符。
但是,operator=(A)
形式是非惯用的,所以无论如何我都倾向于使用operator=(const A&) = delete
。它具有相同的效果。
N.B。没有理由将已删除的函数声明为私有,实际上它会导致更糟糕的诊断。根据我的经验,公开和删除效果更好。
这里还需要一个析构函数吗?
需要什么?这取决于你的默认构造函数。