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

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

本文关键字:是否 只想 自定义 赋值运算符      更新时间:2023-10-16

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

A& operator=(const A&);

如果我不为operator=指定确切的参数,它会起作用吗
我的意思是:

void operator=(void);

返回的值是正确的,我可以写任何我想写的东西,但参数类型呢
这会覆盖类的默认operator=吗?

从C++标准草案的12.8p17开始:

用户声明的复制赋值运算符X::operator=是类X的非静态非模板成员函数,仅具有一个类型为XX&const X&volatile X&const volatile X&的参数。

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

请注意,类似的内容也适用于移动分配运算符,请参见12.8p19:

用户声明的移动赋值运算符X::operator=是类X的非静态非模板成员函数,只有一个类型为X&,常量X&,易失性X&,或常量易失性X&。

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

可以有不同类型的赋值。编译器可能只生成复制赋值移动赋值

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的变体,这些变体符合复制/移动分配的条件。当您禁用复制分配时,移动分配的自动生成也将被禁用。如果禁用移动分配,我认为仍然会生成复制分配。如果禁用任何不能作为复制或移动分配的内容,则仍会生成复制/移动分配。

这是当前标准中用户声明的副本分配运算符的确切定义(§12.8,第17页):

用户声明的复制赋值运算符X::operator=是非静态的CCD_ 14的非模板成员函数类型CCD_ 15或CCD_。

备注:

  • 重载赋值运算符必须声明为只有一个参数见13.5.3
  • 一个类可以声明多种形式的复制赋值运算符
  • 如果类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标准中删除

现在,您可以将函数设置为Defaulted或Deleted。

现在,您可以直接写入要禁用复制的内容。

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

您还可以显式地通知编译器您想要类的默认副本。通过这种方式,您可以提供自定义的默认构造函数,并且仍然可以从编译器中获得其他编译器生成方法的默认版本。

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