当我只想禁用它时,自定义赋值 operator=() 的签名是否重要?

Does signature of custom assignment operator=() matter when I just want to disable it?

我需要禁用复制赋值运算符。这将起作用:

A& operator=(const A&);

如果我不为 operator= 指定确切的参数,它会工作吗?
我的意思是这样的:

void operator=(void);

返回值是对的,我随便写,但是参数类型呢?
这会覆盖 class 的默认值 operator= 吗?

来自C++标准草案的12.8p17

A user-declared copy assignment operator X::operator= is a non-static non-template member function of class X with exactly one parameter of type X, X&, const X&, volatile X& or const volatile X&.

我想这比任何其他测试或示例代码的回复都要好。

请注意,类似的内容也适用于移动赋值运算符,请参阅 12.8p19:

A user-declared move assignment operator X::operator= is a non-static non-template member function of class X with exactly one parameter of type X&&, const X&&, volatile X&&, or const volatile X&&.

这些也证实了,正如您所猜测的,return 值类型无关紧要。

这是来自 current standard(§ 12.8 第 17 页)的用户声明的复制赋值运算符的精确定义:

A user-declared copy assignment operator X::operator= is a non-static non-template member function of class X with exactly one parameter of type X, X&, const X&, volatile X& or const volatile X&.

备注:

  • 重载的赋值运算符必须声明为只有一个 范围;见 13.5.3。
  • 可以为 class 声明一种以上形式的复制赋值运算符。
  • 如果class X只有一个带有X&类型参数的复制赋值运算符,则不能将const X类型的表达式赋值给X类型的对象。

示例:

struct X {
X();
X& operator=(X&);
};
const X cx;
X x;
void f() {
x = cx; // error: X::operator=(X&) cannot assign cx into x
}

此外,请使用 从 C++11 标准中删除

您现在可以将函数设置为默认或已删除。

您现在可以直接写信说您想禁用复制。

class A {
A(const A&) = delete;
A& operator=(const A&) = delete;    // Disallow copying
};

您还可以明确通知编译器您需要 class 的默认副本。这样您就可以提供自定义默认构造函数,并且仍然可以从编译器获得其他编译器生成的方法的默认版本。

class B {
    B(const Y&) = default;
    B& operator=(const B&) = default;   // default copy 
};

可以有不同类型的作业。只有 copy assignmentmove assignment 可能由编译器生成。如果没有 copy/move 分配,则会生成它们。因此,如果您想禁用复制 and/or 移动赋值,参数类型确实很重要,尽管有一些灵活性,因为复制赋值可以使用不同的参数类型。不过,return 类型无关紧要。

class A {
public:
    void operator=() = delete; // not legal: assignment takes exactly one argument
    void operator=(A) = delete; // OK: copy assignment disabled
    void operator=(A&) = delete; // OK: copy assignment disabled
    void operator=(A const&) = delete; // OK: copy assignment disabled
    void operator=(A&&) = delete; // OK: move assignment disabled
};

还有一些变体将 const 替换为 volatileconst volatile 符合 copy/move 分配条件。当您禁用复制分配时,移动分配的自动生成也将被禁用。如果您禁用移动分配,我认为仍会生成复制分配。如果禁用任何不能复制或移动赋值的内容,仍会生成 copy/move 赋值。