5

给定如下代码:

void f()
{
   int i;
   i = 0;
}

由于简单的分配,系统是否有可能引发异常?

[编辑:对于那些说“不会发生异常”的人,您能否指出 C++ 标准中说明这一点的部分的方向?我很难找到它。]

4

5 回答 5

7

尽管您可能很难在标准中找到它的保证,但一个简单的经验法则是,任何在 C 中合法的东西都可能无法抛出。[编辑:我所知道的最接近这种效果的直接陈述是在§15/2,它说:

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

反过来看,不执行 throw 表达式的代码不会引发异常。]

投掷基本上限于两种可能性:第一种是调用UB。第二个是做一些 C++ 独有的事情,例如分配给重载的用户定义类型operator =,或使用new表达式。

编辑:就作业而言,它可以抛出很多方法。显然,加入赋值运算符本身就可以做到这一点,但还有很多其他的。举例来说,如果源类型与目标类型不匹配,您可能会通过源中的强制转换运算符或目标中的构造函数获得转换——其中任何一个都可能抛出。

于 2012-05-16T16:08:35.467 回答
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 的新版本)

于 2012-05-16T16:13:25.050 回答
3

如果您担心将0(具有 type int)分配给 int,则标准的第 5.17 节非常准确地指定了分配操作的语义,并且不会发生异常。如果您担心将任意表达式分配给int,第 5.17 节说“表达式被隐式转换为左操作数的 cv 非限定类型。”取决于右操作数的实际类型:

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

  • 如果它是一个浮点值,则结果是未定义的行为,如果截断为零后的值不能在 an 中表示int,则行为未定义(因此您可能会遇到异常)

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

如果您担心分配其他类型:对于每组非类类型,都有一个类似上面的规则列表,但唯一可能的例外是类型转换的结果。对于类类型,operator=将使用 。这可能会引发异常,具体取决于其中的内容。

于 2012-05-16T16:33:35.153 回答
2

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

于 2012-05-16T16:07:25.890 回答
0

如果它只是一个int,那么不 - 它不会抛出。

如果它是更复杂的东西,例如向量,那么它可能会由于多种原因而抛出(例如分配失败或来自辅助线程的更改)。

于 2012-05-16T16:07:04.323 回答