我需要禁用复制赋值运算符。这将有效:
A& operator=(const A&);
如果我没有为operator=
指定确切的参数,它会起作用吗?
我的意思是这样的:
void operator=(void);
返回值是对的,我可以写任何我想要的,但参数类型怎么样?
这会覆盖类的默认operator=
吗?
答案 0 :(得分:13)
来自C ++标准草案的12.8p17:
用户声明的复制赋值运算符
X::operator=
是类X
的非静态非模板成员函数,其中只有一个类型X
,X&
的参数,const X&
,volatile X&
或const volatile X&
。
我想这比任何其他测试或示例代码都要好。
请注意,类似的内容也适用于移动赋值运算符,请参阅12.8p19:
用户声明的移动赋值运算符X :: operator =是类X的非静态非模板成员函数,其中只有一个类型为X&&&&&&&&&&&&&& ,或const volatile X&&。
这些也证实,正如您所猜测的那样,返回值类型并不重要。
答案 1 :(得分:8)
可以有不同类型的作业。编译器可能只生成复制分配和移动分配。如果没有复制/移动分配,则生成它们。因此,如果要禁用复制和/或移动赋值,则参数类型确实很重要,尽管存在一些灵活性,因为复制赋值可以使用不同的参数类型。但是,返回类型并不重要。
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
替换volatile
或const volatile
符合复制/移动分配的变体。禁用复制分配时,也将禁用自动生成移动分配。如果禁用移动分配,我认为仍会生成复制分配。如果禁用任何不能复制或移动分配的内容,仍会生成复制/移动分配。
答案 2 :(得分:5)
这是来自current standard的用户声明的副本赋值运算符的精确定义(第12.8页,第17页):
用户声明的复制赋值运算符
X::operator=
是非静态的class X
的非模板成员函数,其中只有一个参数 输入X, X&, const X&, volatile X&
或const volatile 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 B {
B(const Y&) = default;
B& operator=(const B&) = default; // default copy
};