在C ++ 11及更高版本的标准中,当通过函数中的值返回类对象时,保证(可能抛出异常)复制ctor是不被调用 - 提供了一个移动ctor是为这个类定义的?背景:假设
struct X {
X() {}
X(const X&) {/* code that might throw exceptions */}
X(X&&) {/* code that never throws exceptions */}
...
};
和
X my_func(some_type& t)
{
X x;
// code that modifies t and x but never throws exceptions
return x;
}
现在,例如,
这样的表达式some_other_func(my_func(t));
如果函数some_other_func(const X&)
没有抛出异常,那么永远不会抛出异常(即,这是否有保证?)如果some_other_func
的签名是some_other_func(X)
?
答案 0 :(得分:4)
The rule is simple: a function is treated as if it can throw exceptions unless it's marked as a function which cannot. A move constructor is a function like any other in this respect. When defined manually, it is considered potentially throwing unless defined noexcept
.
Implicitly defaulted functions (i.e. the auto-provided copy & move operations) generally follow the logic of: declared as noexcept
if and only if all functions which it calls are noexcept
.
答案 1 :(得分:1)
异常永远不会在一个格式良好的C ++程序中自发生成,该程序只会限定定义的行为。
如果您的代码是一个格式良好的程序,您永远不会调用或与允许抛出异常的语言或库特性交互,并且您编写的代码不会抛出异常(显式),那么结果就是赢得的代码&# 39;抛出异常。
除非您将函数和方法标记为noexcept
,否则编译器和标准库可能没有意识到这一点,并且可能假设您的代码抛出异常(即使它不能)。在某些情况下,这可能会导致编译器分配内存并抛出异常,因为您的代码可能会抛出异常,或者调用不同的方法(例如在某些向量操作中复制而不是移动)。
应该做的是将X(X&&)
和X()
标记为noexcept
,这个特殊问题就会消失。
尽管如此,您的确切代码不会抛出,除非some_other_function
没有X
,而是从{{X
创建的类型1}}并且该操作可能会抛出,或some_other_function
的主体可能抛出。