看着我偶然发现的一些代码:
throw /*-->*/new std::exception ("//...
我一直认为你不需要/你不应该在这里使用 new。 正确的方法是什么,两者都可以吗? 如果可以,有什么区别吗?
new
顺便说一句,我可以看到,而“抓取”与 PowerShell 提升库从来没有使用 throw new。
throw new
另外,我还找到了一些使用 throw gcnew的 CLI 代码,可以吗?
throw gcnew
抛出异常时不需要使用 new。
只要写:
throw yourexception(yourmessage);
然后捕捉到:
catch(yourexception const & e) { //your code (probably logging related code) }
请注意,yourexception应该直接或间接地从 std::exception派生出来。
yourexception
std::exception
如果呼叫站点期望捕获 std::exception*,则抛出 new std::exception是正确的。但是没有人会期望捕获指向异常的指针。即使您编写了文档说明,而且人们阅读了文档,他们仍然容易忘记并试图捕获对 std::exception对象的引用。
std::exception*
new std::exception
C + + 常见问题解答对此进行了很好的讨论:
基本上就是“除非有充分的理由不这么做,不然就通过参考文献抓住他”。避免通过值捕获,因为这会导致复制,并且复制的行为可能与抛出的行为不同。只有在非常特殊的情况下,你才能用指针捕捉。”
抛出和捕获异常的常规方法是抛出异常对象并通过引用(通常是 const引用)捕获它。C + + 语言要求编译器生成适当的代码来构造异常对象,并在适当的时候正确地清理它。
const
抛出指向动态分配对象的指针从来都不是一个好主意。异常应该使您能够在出错情况下编写更健壮的代码。如果按照常规方式抛出异常对象,那么可以确保异常对象是否被一个指定正确类型的 catch 子句捕获,是否被 catch (...)捕获,然后是否重新抛出异常对象将在适当的时候被正确地销毁。(唯一的例外是,如果它从未被捕获,但无论从哪种角度看,这都是一种不可恢复的情况。)
catch (...)
如果你抛出一个指向动态分配对象的指针,你必须确保无论调用堆栈在你想抛出异常的时候是什么样子,都有一个 catch 块来命名正确的指针类型和适当的 delete调用。除非该块重新抛出该异常,否则 catch (...)永远不能捕获该异常,该异常随后被另一个 catch 块捕获,而这个 catch 块确实正确处理了该异常。
delete
实际上,这意味着您已经采用了异常处理特性,这使得编写健壮的代码变得更加容易,并且使得编写在所有情况下都是正确的代码变得非常困难。这抛开了一个问题,那就是客户机代码几乎不可能作为库代码使用,因为客户机代码并不期待这个特性。
运算符 new 不能保证它永远不会引发异常。出于这个原因,使用它来抛出“有效”(预期的)异常将产生一个不能保证不会崩溃的代码。由于一次可能只有一个异常,并且您的程序试图在其中任何一个异常被捕获之前抛出两个异常,所以实现能做的最好的事情就是立即中止您的程序,例如通过调用 std: : finally。