在看一些代码时,我偶然发现:
throw /*-->*/new std::exception ("//...
我一直以为您不需要/不应该new
在这里使用。
正确的方法是什么,都可以,如果可以的话,有什么区别吗?
顺便说一句,从我用PowerShell增强库“抓取”时可以看到,从未使用过throw new
。
PS还发现了一些使用的CLI代码throw gcnew
。那样行吗?
在看一些代码时,我偶然发现:
throw /*-->*/new std::exception ("//...
我一直以为您不需要/不应该new
在这里使用。
正确的方法是什么,都可以,如果可以的话,有什么区别吗?
顺便说一句,从我用PowerShell增强库“抓取”时可以看到,从未使用过throw new
。
PS还发现了一些使用的CLI代码throw gcnew
。那样行吗?
Answers:
引发和捕获异常的常规方法是抛出异常对象并通过引用(通常是const
引用)来捕获它。C ++语言要求编译器生成适当的代码以构造异常对象,并在适当的时间对其进行适当的清理。
将指针指向动态分配的对象绝不是一个好主意。异常应该使您能够在遇到错误情况时编写更强大的代码。如果以常规方式抛出异常对象,则可以确保是否通过命名正确类型的catch子句捕获该异常对象,通过a捕获该异常对象,catch (...)
然后重新抛出该异常对象,该异常对象将在适当的时间正确销毁。(唯一的例外是,即使它从未被捕获,但是无论您采用哪种方式,这都是不可恢复的情况。)
如果将指针抛出给动态分配的对象,则必须确保无论您想抛出异常的那一面是什么调用堆栈,都存在一个catch块,该块命名正确的指针类型并具有适当的delete
调用。catch (...)
除非该块重新引发了异常,然后再被另一个正确处理该异常的catch块捕获,则决不能捕获您的异常。
实际上,这意味着您已经采用了异常处理功能,该功能应该使编写健壮的代码更加容易,并且使编写在所有情况下正确的代码变得非常困难。这就排除了一个问题,几乎不可能充当不会期望此功能的客户端代码的库代码。
new
引发异常时无需使用。
写就好了:
throw yourexception(yourmessage);
并捕获为:
catch(yourexception const & e)
{
//your code (probably logging related code)
}
注意,yourexception
应该std::exception
直接或间接地派生。
new
?为什么yourexception
从std::exception
?
std::exception
是一个类型,您不能抛出一个类型,必须抛出一个对象。所以语法应该是这样:throw std::exception();
可以编译。现在,这到底有多好,是一个完全不同的问题。
new std::exception
如果呼叫站点希望捕获,则抛出正确std::exception*
。但是没有人会期望得到指向异常的指针。即使您的文档是函数的功能,即使人们阅读了文档,他们仍然有可能忘记并尝试捕获对std::exception
对象的引用。
new std::exception
仅当调用站点希望捕获指针并且希望接管分配异常的管理并且永远不会在任何情况下被未明确捕获的函数调用函数时,抛出才是正确的正确的指针(catch(...)
或根本没有处理),否则将发生对象泄漏。简而言之,这可以近似为“从不”。
C ++常见问题对此进行了很好的讨论:
基本上,“除非有充分的理由不按引用进行捕获。请避免按值进行捕获,因为这会导致生成副本,并且副本可能具有与抛出的行为不同的行为。只有在非常特殊的情况下,才应使用指针进行捕获。 ”
A
与该类型是不同的,A*
所以如果我这样做,throw A()
我将无法抓住catch(A* e)
它,因为它是完全不同的类型。
throw gcnew
将是有用的。如果您希望托管代码捕获异常。有人可以纠正我吗?