考虑以下代码:
class Object
{
public:
Object& operator=(const Object& object) noexcept = default;
private:
int i;
// ...
};
您能否告诉我明确声明复制赋值运算符不引发异常并且具有默认实现是否有任何影响?
是否会检查自动生成的代码以防止自我分配?
考虑以下代码:
class Object
{
public:
Object& operator=(const Object& object) noexcept = default;
private:
int i;
// ...
};
您能否告诉我明确声明复制赋值运算符不引发异常并且具有默认实现是否有任何影响?
是否会检查自动生成的代码以防止自我分配?
将生成一个按位复制的构造函数。没有任何保护措施可以防止分配给自己,但这已经可以理解了。显然,按位复制不会抛出异常。
noexcept 这个词有意义吗?在这种情况下似乎不是。但是根据文档,复制构造函数是指“可能引发异常” https://en.cppreference.com/w/cpp/language/noexcept_spec
但是指定默认值是个好主意——这样你就可以明确声明你需要这个构造函数。这正是本应如此。
不过,我会回答,因为在我看来,可用的答案至少不完整......
将生成一个赋值语句,执行每个字段的赋值。因此,如果该字段不是 simple
int
,而是更复杂的字段,则会调用该类型对应的赋值运算符。将不会检查自我分配。
noexcept
与默认赋值运算符的签名不匹配,因此例如 GCC,根本不会使用它进行编译。VC++ 将毫无疑问地编译,但在这种情况下,当“与他一样与叛徒一起”抛出异常时(c) - 调用terminate()
时不可能拦截生成的异常。这是 VC++ 的代码,演示了所说的内容 -
对于 GCC,正如我所说,不会有编译
noexcept
,但没有它 - 请参阅https://ideone.com/Xj8LUSnoexcept
可能允许编译器执行一些原本不可用的优化的函数。由于您的语句不能抛出异常,它可以让编译器生成更快的代码,而不必担心在运行时保存堆栈。
标准库容器(例如
std::vector
)知道 noexcept 并将使用它来确定是否在某些地方使用移动语义或复制语义。在这种情况下,您的赋值语句默认,这意味着默认分配所有成员不应引发异常,否则整个代码将在调用 std::terminate 时崩溃。