C++:抛出异常时,是否使用'new'?

28

在C++中使用 throw new FoobarException(Baz argument); 还是 throw FoobarException(Baz argument); 是合适的吗?

当捕获异常时,我总是使用 catch(FoobarException& e) "以防万一",但我从未找到一个确切的答案,是否必须在 C++(Java 明确要求)中使用 new,或者这只是程序员的个人偏好。


2
我认为如果你通过指针抛出异常并尝试通过引用捕获,它不会起作用,对吗? - Tamás Szelei
2
如果您使用new,那么catch(FoobarException&)将无法捕获您的对象。new创建指针。 - Benjamin Lindley
2个回答

35

C++中的异常应以值的形式抛出,并通过引用捕获。

因此,这是正确的方法:

try
{
    throw FoobarException(argument);
}
catch( const FoobarException &ex )
{
    cout << ex.what() << endl;
}

不要抛出使用new创建的异常,因为谁负责删除它没有明确定义。此外,在错误处理期间执行分配可能会引发另一个异常,从而掩盖原始问题。

您不必通过const引用捕获(非const也可以正常工作),但我仍然喜欢这样做。但是,您应该始终通过引用(而不是值)进行多态异常捕获。如果不这样做,异常的类型可能会被切片。


为什么异常应该始终通过引用而不是值来捕获?您是在说由于将派生对象按值传递给期望基类对象参数的方法而导致的对象切片问题吗? - Destructor

8

除非有特殊的要求,否则我总是按值抛出并通过const引用捕获。这是因为new本身也可能会引发异常,在错误处理期间最好避免可能导致异常的事情。


是的,当另一个异常处于活动状态时抛出异常基本上是被禁止的(我认为这是UB),因此标准的 new 不适用。如果你真的必须使用一些非抛出分配,但那仍然是疯狂的 :-) - Kerrek SB
1
我的建议是:补充一下@KerrekSB的明智建议,这实际上是定义行为(请参见http://en.cppreference.com/w/cpp/error/terminate)。前面提到的链接还指出了许多其他最好避免的事情(例如从析构函数中抛出异常,因为那样可能会在为先前抛出的异常展开堆栈时引发异常)。 - Rob

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接