C++标准实际上保证抛出表达式的操作数提供抛出的值吗?

ohfgkhjo  于 2022-12-27  发布在  其他
关注(0)|答案(1)|浏览(127)

在阅读标准中异常处理的细节时,我注意到它似乎从未实际指定throw表达式的操作数将为抛出的异常对象提供值。
描述throw表达式语义的[expr.throw]部分只说了以下内容:
用一个操作数计算throw-expression会抛出一个异常(公式15 - 1);异常对象的类型是通过从操作数的静态类型中移除任何顶层cv限定符并将类型从“T的数组”或“返回T的函数”分别调整为“指向T的指针”或“指向返回T的函数的指针”来确定的。
因此,如果有人说throw 5,异常对象的类型必须是int,这并不是说异常对象的值必须是5,而不是7int类型的任意值,15.1节[except.throw]仍然是模糊的,它是这样说的:
传递一个对象,并且该对象的类型决定哪些处理程序可以捕获它。
同样,操作数的类型很重要,但操作数的值无关紧要。
抛出一个异常复制初始化一个临时对象,称为异常对象。
临时对象是复制初始化的,但没有提到这个临时对象有任何特定的值。编译器可以从一个值为7的纯右值int复制初始化这个临时异常对象,如果它愿意的话,它仍然满足这个子句,因为它确实复制初始化了一个临时对象。
如果我有这个程序

#include <cassert>
void f() {
    try {
        throw 5;
    } catch (int x) {
        assert(x == 5);
    }
}

C++标准中有什么特定的措辞可以保证这个Assert永远不会失败呢?据我所知,标准只保证异常对象将具有类型int,但不保证它将具有任何特定的值,也就是说,如果临时对象初始化为7,则Assert可能会失败。似乎没有提到对象/值/用于创建异常对象的throw表达式的操作数的结果。

guykilcj

guykilcj1#

出发地:n4917

14.4处理异常[except. handle]

第十四段:
14异常声明所声明的类型为cv T或cv T &的变量从类型为E的异常对象初始化,如下所示:
它接着描述了使用了什么构造函数/初始化器等(这是你所期望的)。但是我们知道它是从"异常对象"创建的,所以我们只需要定义异常对象。
这就引出了这样一个问题:"什么是异常

14.2抛出异常[except. throw]

第三款:
3 Throwing an exception copy-initializes (9.4, 11.4.5.3) a temporary object, called theexception object. If the type of the exception object would be an incomplete type, an abstract class type (11.7.4), or a pointer to an incomplete type other than cv void the program is ill-formed.

相关问题