6

§[except.throw]中,标准说抛出异常从 throw 表达式复制初始化异常对象

抛出异常复制初始化(11.6,15.8)一个临时对象,称为异常对象

那么为什么下面的代码会在 C++17 上编译呢?

class Exception {
public:
   Exception() = default;
   Exception(Exception&&) = delete;
   Exception(const Exception&) = delete;
};

int main() {
    throw Exception{};
    return 0;
}

https://wandbox.org/permlink/R3WfzfnBAORTLVSy

复制初始化不包括任何符合prvalue省略的情况(从我看来)。那么为什么上面的代码在 C++17 中编译呢?

4

1 回答 1

8

从最近的标准草案

11.6 [dcl.init]/15

以大括号或等于初始化器或条件 (9.4) 的形式发生的初始化,以及在参数传递、函数返回、抛出异常 (18.1)、处理异常 (18.3) 和聚合成员初始化中(11.6.1),称为复制初始化。

T x = T();复制初始化的示例也是如此。抛出异常和许多其他情况也是如此。

复制初始化的作用在 11.6 的其他部分中定义(以及其他形式的初始化)。初始化器中纯右值的相关部分是:

11.6 [dcl.init]/17.6.1

如果初始化表达式是纯右值并且源类型的 cv 非限定版本与目标类是同一类,则使用初始化表达式初始化目标对象

这也称为保证省略。如果初始化表达式是匹配类型的纯右值表达式,则使用纯右值表达式直接构造初始化的目标。

于 2018-08-28T00:16:47.917 回答