在阅读标准中的异常处理细节时,我注意到它似乎并没有真正指定throw表达式的操作数将为抛出的异常对象提供值。
描述throw表达式语义的[expr.throw]部分仅表示:
使用操作数计算throw-expression会抛出一个异常(15.1);异常对象的类型是通过从操作数的静态类型中删除任何顶级cv限定符并将类型从“数组T”或“函数返回T”调整为“指针”来确定的。分别为“T”或“指向函数返回T的指针”。
因此,如果有人说throw 5
,则异常对象的类型必须为int
。实际上,这似乎并不是说异常对象的值必须是5
而不是7
或任何其他类型int
的任意值。第15.1节[except.throw]继续同样模糊不清。它说的是:
传递一个对象,该对象的类型确定哪些处理程序可以捕获它。
再一次,操作数的类型很重要,但不是操作数的值。
抛出异常拷贝 - 初始化一个称为异常对象的临时对象。
临时对象是复制初始化的,但没有提及具有任何特定值的临时对象。如果需要,编译器可以从值int
的prvalue 7
复制初始化临时异常对象,并且它仍然会满足此子句,因为它复制初始化临时对象。 永远不会提到throw表达式的操作数。
所以,如果我有这个程序:
#include <cassert>
void f() {
try {
throw 5;
} catch (int x) {
assert(x == 5);
}
}
C ++标准中的哪些具体措辞保证了这个断言永远不会失败?据我所知,标准只保证异常对象具有类型int
,但不保证它具有任何特定值,即如果临时对象的初始化值为{{{}},则断言可能会失败1}}。似乎没有提到用于创建异常对象的throw表达式的操作数的对象/值/结果。