抛出新的std :: exception vs throw std :: exception

时间:2012-06-08 11:51:59

标签: c++ exception

在看一些代码时我偶然发现:

throw /*-->*/new std::exception ("//...

我一直认为你不需要/你不应该在这里使用new 什么是正确的方法,都可以,如果有的话有什么不同吗?

BTW从我所看到的,而使用PowerShell提升库的“grepping”永远不会使用throw new

P.S。我也发现了一些使用throw gcnew的CLI代码。那可以吗?

5 个答案:

答案 0 :(得分:79)

抛出和捕获异常的传统方法是抛出异常对象并通过引用捕获它(通常是const引用)。 C ++语言要求编译器生成适当的代码来构造异常对象并在适当的时候正确地清理它。

抛出指向动态分配对象的指针绝不是一个好主意。异常应该使您能够在错误条件下编写更强大的代码。如果以常规方式抛出异常对象,您可以确定它是否被一个用catch (...)命名正确类型的catch子句捕获,然后是否被重新抛出它将被正确销毁在适当的时候。 (唯一的例外是,如果它从未被捕获,但这是一个不可恢复的情况,无论你怎么看待它。)

如果你抛出一个指向一个动态分配的对象的指针,你必须确保无论调用堆栈在你想要抛出异常的那一点看起来是什么,都有一个catch块,它命名正确的指针类型并具有相应的{ {1}}致电。您的异常绝不能被delete捕获,除非该块重新抛出异常,然后捕获该异常是另一个正确处理异常的catch块。

实际上,这意味着您已经采用了异常处理功能,这使得编写健壮的代码变得更加容易,并且很难编写在所有情况下都正确的代码。这就抛开了一个问题,即几乎不可能充当客户端代码的库代码而不期望这个功能。

答案 1 :(得分:28)

抛出异常时无需使用new

只需写下:

throw yourexception(yourmessage);

并抓住:

catch(yourexception const & e)
{
      //your code (probably logging related code)
}

请注意,yourexception应直接或间接来自std::exception

答案 2 :(得分:22)

如果呼叫网站希望捕获new std::exception,则投掷std::exception*是正确的。但没有人会期望抓住指向异常的指针。即使您记录了您的功能所做的事情以及人们阅读文档,他们仍然会忘记并尝试捕获对std::exception对象的引用。

答案 3 :(得分:7)

C ++ FAQ对此进行了很好的讨论:

  1. https://isocpp.org/wiki/faq/exceptions#what-to-catch
  2. https://isocpp.org/wiki/faq/exceptions#catch-by-ptr-in-mfc
  3. 基本上“除非有充分理由不通过引用捕获。避免按价值捕获,因为这会导致复制并且副本可能与抛出的内容有不同的行为。只有在非常特殊的情况下才能捕获通过指针。“

答案 4 :(得分:1)

new运算符不能保证它永远不会引发异常。因此,将其用于引发“有效”(预期)异常将产生无法保证不会崩溃的代码。由于一次可能只有一个异常,并且您的程序会尝试在引发任何异常之前抛出两个异常,因此实现的最佳做法是立即中止您的程序,例如通过调用std :: terminate。