当我只想禁用它时,自定义赋值 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 assignment 和 move 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
替换为 volatile
或 const volatile
符合 copy/move 分配条件。当您禁用复制分配时,移动分配的自动生成也将被禁用。如果您禁用移动分配,我认为仍会生成复制分配。如果禁用任何不能复制或移动赋值的内容,仍会生成 copy/move 赋值。
我需要禁用复制赋值运算符。这将起作用:
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 classX
with exactly one parameter of typeX
,X&
,const X&
,volatile X&
orconst 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 ofclass X
with exactly one parameter of typeX, X&, const X&, volatile X&
orconst 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 assignment 和 move 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
替换为 volatile
或 const volatile
符合 copy/move 分配条件。当您禁用复制分配时,移动分配的自动生成也将被禁用。如果您禁用移动分配,我认为仍会生成复制分配。如果禁用任何不能复制或移动赋值的内容,仍会生成 copy/move 赋值。