C++ 可以在C++;抛出异常?

C++ 可以在C++;抛出异常?,c++,exception,try-catch,C++,Exception,Try Catch,给定如下代码: void f() { int i; i = 0; } 系统是否可能因为简单的赋值而引发异常 编辑:对于那些说“没有例外不能发生”的人,你能指出C++标准部分的方向吗?我说:“我找不到它。”< /p> < p>如果它只是 int >代码>,则不-它不会投掷。< /P> 如果它是更复杂的东西,比如向量,那么它可能会因为许多原因(例如分配失败或从辅助线程进行更改)而抛出异常。它只能在一种情况下抛出异常:当重载运算符=()时,这两种类型的抛出;类似地,当需要转换时,转换构造

给定如下代码:

void f()
{
   int i;
   i = 0;
}
系统是否可能因为简单的赋值而引发异常


编辑:对于那些说“没有例外不能发生”的人,你能指出C++标准部分的方向吗?我说:“我找不到它。”< /p> < p>如果它只是<代码> int >代码>,则不-它不会投掷。< /P>
如果它是更复杂的东西,比如向量,那么它可能会因为许多原因(例如分配失败或从辅助线程进行更改)而抛出异常。

它只能在一种情况下抛出异常:当重载
运算符=()时,这两种类型的抛出;类似地,当需要转换时,转换构造函数或
运算符T()
也可以抛出。这取决于具体的实现——要确定它是否会抛出,请在您正在使用的库的文档中查找有关它的信息。

尽管您可能很难在标准中找到它的保证,但一个简单的经验法则是,任何在C中合法的东西都可能不会抛出。[编辑:据我所知,最接近直接声明的是§15/2,其中指出:

执行抛出表达式的代码被称为“抛出异常;”[…]

反过来看,不执行抛出表达式的代码不会抛出异常。]

抛出基本上限于两种可能性:第一种是调用UB。第二个是对C++做一些独特的事情,例如分配给用户定义的类型:重载<代码>运算符=<代码>,或者使用<代码>新< /COD>表达式。
编辑:就作业而言,它可以抛出很多方法。显然,加入赋值操作符本身就可以做到这一点,但还有相当多的其他操作符。例如,如果源类型与目标类型不匹配,您可能会通过源中的强制转换运算符或目标中的构造函数获得转换,两者都可能抛出

有相当多的事情看起来像是可以以某种方式抛出的作业:

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中的新版本)

如果您关心将
0
(其类型为
int
)分配到 标准的§5.17非常准确地规定了 分配操作,并且在任何情况下都不会发生异常。 如果您担心将任意表达式赋给
int
, §5.17规定“表达式隐式转换为 cv左操作数的非限定类型。“取决于实际类型 右操作数的类型:

  • 如果它是整数类型,如果实际值不能在
    int
    中表示,则结果由实现定义(C标准更明确:它必须导致具有实现定义值的
    int
    ,否则您将得到实现定义的信号)

  • 如果是浮点值,则结果为未定义行为如果截断为零后的值无法在
    int
    中表示,则行为为未定义(因此可能会出现异常)

  • 如果是用户定义的类型,则将调用用户定义的转换运算符。该运算符可能引发异常


如果您关心分配其他类型:对于每组 非类类型,有一个类似于上面的规则列表,但只有 可能的异常将是类型转换的结果。对于类 类型,将使用
运算符=
。该运算符可以引发异常,
取决于其中的内容。

类型始终是
int
,RHS始终是文字吗?还是您在询问一般情况?(您显示的内容也不是作业)谢谢你抓住了这一点。我编辑了这个例子。对于你的第一个问题,实际上,对于这两个问题。实现可以自由地对资源施加限制,不是吗?如果是的话,“没有更多的堆栈,没有多余的寄存器”(至少在理论上)难道不是一个抛出的有效理由,并且只有在第一次使用时才被发现吗?理论上是的。VC++6(例如)做过类似的事情——但结果很糟糕,VC++已经不存在了,我至少会有点惊讶地看到其他人也会很快尝试使用它。@JerryCoffin对“C中的合法性”给出了足够严格的定义将一个浮点分配给一个int可能导致未定义的行为,并且异常与其他未定义行为的情况一样有效(虽然可能不是从实现角度的质量)。“Ad林地”我找不到,但是在C标准中(我非常确信C++遵循这里的C)。,耗尽资源(堆栈等)是未定义的行为。这意味着一切都会发生,尽管从实现质量的角度来看…分配失败被定义为引发异常(除非您使用自定义分配器)。在修改向量时从另一个线程访问向量是未定义的行为,任何事情都可能发生。但是,从实现质量的角度来看,我不希望出现异常。