对于不可移动类型,以下内容是否足够(从最佳实践的角度来看)?
class A
{
A(const A&) = delete;
A(A&&) = delete;
A& operator=(A) = delete;
public:
A();
};
还是我必须单独删除复制/移动赋值运算符?这里还需要析构函数吗?
是的,声明复制构造函数和复制赋值运算符deleted
就足够了。由于您要声明复制构造函数和复制赋值运算符,因此不会自动生成移动构造函数和移动赋值运算符。您不需要显式声明它们deleted
。
来自 §12.8/9(强调添加)
如果类 X 的定义没有显式声明移动构造函数,当且仅当
- X 没有用户声明的复制构造函数,
- X 没有用户声明的复制赋值运算符时,才会将其隐式声明为默认值,
— X 没有用户声明的移动赋值运算符,
— X 没有用户声明的析构函数,并且
— 移动构造函数不会被隐式定义为已删除。
从 §12.8/20 开始(强调添加)
如果类 X 的定义没有显式声明移动赋值运算符,当且仅当
- X 没有用户声明的复制构造函数,
- X 没有用户声明的移动构造函数时,才会将其隐式声明为默认值,
— X 没有用户声明的复制赋值运算符,
— X 没有用户声明的析构函数,并且
— 移动赋值运算符不会被隐式定义为已删除。
根据 [class.copy]/17operator=(A)
是一个有效的复制赋值运算符,所以是的,声明它已删除足以抑制隐式移动赋值运算符,因此与删除的复制构造函数一起将使类不可复制和不可移动.
不过,您的课程比必要的要复杂,您所需要的只是:
class A
{
A(const A&) = delete;
A& operator=(A) = delete;
public:
A();
};
用户声明的复制构造函数抑制隐式移动构造函数,用户声明的复制赋值运算符抑制隐式移动赋值运算符。
然而,这种operator=(A)
形式是不习惯的,所以我还是倾向于使用operator=(const A&) = delete
。它具有相同的效果。
注意,没有理由将已删除的函数声明为私有,实际上它会导致更糟糕的诊断。根据我的经验,公开和删除效果更好。
这里还需要析构函数吗?
需要什么?这取决于你的默认构造函数做什么。