【问题标题】:C++: Throwing exceptions, use 'new' or not?C++:抛出异常,是否使用“新”?
【发布时间】:2011-10-11 17:19:27
【问题描述】:

使用throw new FoobarException(Baz argument);throw FoobarException(Baz argument);是否合适?

捕捉时我总是使用catch(FoobarException& e)“以防万一”,但无论是否必须在 C++(绝对是 Java)中使用 new 或是否只是程序员的偏好,我都找不到可靠的答案。

【问题讨论】:

  • 如果你通过指针抛出并尝试通过引用捕获,我认为它不会捕获,是吗?
  • 如果你使用 new,那么catch(FoobarException&) 将不会捕获你的对象。 new 创建指针。

标签: c++ exception throw


【解决方案1】:

C++ 中的异常应该按值抛出,并通过引用捕获。

所以这是正确的方法:

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

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

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

【讨论】:

  • 为什么异常应该总是通过引用而不是值来捕获?您是在说对象切片问题,因为将派生对象按值传递给方法需要基类对象的参数?
【解决方案2】:

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

【讨论】:

  • 没错,基本上禁止在另一个异常处于活动状态时抛出异常(我认为它是 UB),所以标准的new 已经过时了。如果你真的需要的话,你可以使用一些非抛出分配,但这仍然很疯狂:-)
  • 我的 2c 的:只是为了添加到 @KerrekSB 的明智建议,它实际上是定义的行为(参见 en.cppreference.com/w/cpp/error/terminate)。上述链接还指出了一些最好避免的其他事情(例如从析构函数中抛出异常,因为这样您可能会在堆栈为先前抛出的异常展开时引发异常)。
猜你喜欢
  • 1970-01-01
  • 2012-06-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多