21

对于不可移动类型,以下内容是否足够(从最佳实践的角度来看)?

class A
{
   A(const A&) = delete;
   A(A&&) = delete;
   A& operator=(A) = delete;
public:
   A();
};

还是我必须单独删除复制/移动赋值运算符?这里还需要析构函数吗?

4

2 回答 2

8

是的,声明复制构造函数和复制赋值运算符deleted就足够了。由于您要声明复制构造函数和复制赋值运算符,因此不会自动生成移动构造函数和移动赋值运算符。您不需要显式声明它们deleted

来自 §12.8/9(强调添加)

如果类 X 的定义没有显式声明移动构造函数,当且仅当
- X 没有用户声明的复制构造函数,
- X 没有用户声明的复制赋值运算符时,才会将其隐式声明为默认值,
— X 没有用户声明的移动赋值运算符,
— X 没有用户声明的析构函数,并且
— 移动构造函数不会被隐式定义为已删除。

从 §12.8/20 开始(强调添加)

如果类 X 的定义没有显式声明移动赋值运算符,当且仅当
- X 没有用户声明的复制构造函数,
- X 没有用户声明的移动构造函数时,才会将其隐式声明为默认值,
— X 没有用户声明的复制赋值运算符,
— X 没有用户声明的析构函数,并且
— 移动赋值运算符不会被隐式定义为已删除。

于 2013-07-04T21:53:03.820 回答
3

根据 [class.copy]/17operator=(A)是一个有效的复制赋值运算符,所以是的,声明它已删除足以抑制隐式移动赋值运算符,因此与删除的复制构造函数一起将使类不可复制和不可移动.

不过,您的课程比必要的要复杂,您所需要的只是:

class A
{
   A(const A&) = delete;
   A& operator=(A) = delete;
public:
   A();
};

用户声明的复制构造函数抑制隐式移动构造函数,用户声明的复制赋值运算符抑制隐式移动赋值运算符。

然而,这种operator=(A)形式是不习惯的,所以我还是倾向于使用operator=(const A&) = delete。它具有相同的效果。

注意,没有理由将已删除的函数声明为私有,实际上它会导致更糟糕的诊断。根据我的经验,公开和删除效果更好。

这里还需要析构函数吗?

需要什么?这取决于你的默认构造函数做什么。

于 2013-07-04T22:41:11.413 回答