给出如下代码:
void f()
{
int i;
i = 0;
}
由于简单的赋值,系统是否可能抛出异常?
[编辑:对于那些说“没有例外不能发生”的人,你能指出我的C ++标准部分的方向吗?我找不到它。]
答案 0 :(得分:7)
虽然你可能很难在标准中找到它的保证,但一个简单的经验法则是,任何在C中合法的东西都可能无法抛出。 [编辑:我最接近直接声明这一点的是§15/ 2,其中说:
执行 throw-expression 的代码被称为“抛出异常;”[...]
反过来看,不执行throw-expression的代码不会抛出异常。]
投掷基本上限于两种可能性:第一种是调用UB。第二种是对C ++做一些独特的事情,例如分配给用户定义的类型,该类型重载operator =
,或使用new
表达式。
编辑:就任务而言,有很多方法可以抛出。显然,投入任务操作员本身就可以做到,但还有相当多的其他人。例如,如果源类型与目标类型不匹配,则可能通过源中的强制转换操作符或目标中的构造函数进行转换 - 其中任何一个都可能抛出。
答案 1 :(得分:6)
有很多东西看起来像是可以抛出这样或那样的任务:
int operator"" _t(const char *) { throw 0; } // C++11 user defined literal
struct foo {
foo(int) { throw 0; }
operator int() { throw 0; }
foo& operator=(int) { throw 0; }
};
int main() {
int i;
i = 0; // can't throw
i = 0_t; // User defined literal throws
foo f = 0; // Constructor throws
i = f; // conversion operator throws
f = 0; // assignment throws
f = f; // both conversion and assignment would like to throw
}
(包括来自C ++ 11的新版本)
答案 2 :(得分:3)
如果您担心将0
(类型为int
)分配给。{
int
,该标准的§5.17非常准确地指出了语义
赋值操作,并且不存在可能发生异常的情况。
如果您担心将任意表达式分配给int
,
§5.17说“表达式被隐含地转换为
cv-unqualified类型的左操作数。“取决于实际类型
正确的操作数:
如果它是整数类型,如果实际值不能用int
表示,则结果是实现定义的(C标准更明确:它必须导致{{1使用实现定义的值,或者您将获得实现定义的信号)
如果它是浮点值,如果截断为零后的值无法在int
中表示,则结果是未定义的行为,行为未定义(因此您可能会遇到异常)< / p>
如果是用户定义的类型,则将调用用户定义的转换运算符。哪个可以抛出异常。
如果您担心分配其他类型:每组
非类类型,有一个像上面这样的规则列表,但是唯一的
可能的异常将是类型转换的结果。上课
类型,将使用int
。哪个可以抛出异常,
取决于其中的内容。
答案 3 :(得分:2)
它只能在一种情况下抛出异常:当这两种类型抛出时重载operator=()
;类似的,当需要转换时,转换构造函数或operator T()
也可以抛出。这取决于确切的实现 - 找出它是否会抛出,在您正在使用的库的文档中查找有关它的信息。
答案 4 :(得分:0)
如果它只是一个int
,那么不 - 它不会抛出。
如果它是一个更复杂的东西,比如矢量,那么它可能会因为多种原因而抛出(例如分配失败或从辅助线程更改)。