C ++ 11:按值返回对象是否在定义move ctor时从不抛出异常?

时间:2017-10-12 09:25:15

标签: c++ c++11 exception return noexcept

在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)

,该怎么办?

2 个答案:

答案 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的主体可能抛出。