代码之家  ›  专栏  ›  技术社区  ›  Curious

throw表达式中是否允许prvalue省略

  •  6
  • Curious  · 技术社区  · 8 年前

    §[except.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中编译?

    1 回复  |  直到 8 年前
        1
  •  8
  •   Yakk - Adam Nevraumont    8 年前

    从最近的 draft standard

    11.6[DCL.init]/15

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

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

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

    11.6[DCL.init]/17.6.1

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

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