【问题标题】:C++ Exception Handling QuestionsC++ 异常处理问题
【发布时间】:2011-04-27 04:48:36
【问题描述】:

1) 为方便起见,我将整个程序放在 try 块中。这样我就可以在我的代码中的任何时候抛出一个异常,并且知道它会以同样的方式被处理。随着程序变得越来越大,这种技术会影响性能吗?

2) 如果对象在超出范围时被释放,为什么抛出一个临时对象是有效的?例如:

类错误:公共 std::exception
{
  私人的:
    魅力;
  私人的:
    错误(字符 *l):m(l){}
    虚拟字符 *what()
    {
      返回米;
    }
};

主函数()
{
  尝试
  {
    抛出错误(“测试”);
  }
  捕获(标准::异常 &e)
  {
    放(e.what());
    返回-1;
  }
  返回0;
}

在throw语句中,临时对象只在try作用域中声明,为什么不会失效?

3) 对于非英语语言的 Windows 操作系统,STL 异常类的 what() 成员是否仍会返回 char* 字符串?或者它可以返回一个wchar_t* 字符串吗?

【问题讨论】:

  • 你真的不应该把你的整个程序放在一个 try 块中。如果你遇到任何错误,你的整个程序就会结束,而不是让你优雅地处理它并继续。这有点违背了例外的目的。
  • 我不同意,如果您在此级别从异常记录有意义的信息,那么它是完全有效的。与调用 std::terminate 相比,它为您提供了更好的信息,如果没有捕获到异常,就会发生这种情况。
  • @JoshD 在我的代码的某些区域内,我可以有更多的 try-catch 块,我可以优雅地处理异常。第一个 try-catch 块是处理程序无法继续执行的致命错误。
  • @radman:我并不是说不应该进行捕捉。我是说在整个程序周围有一个巨大的 try 块不如拥有更细粒度的 try 和 catch 块有用。我同意捕获异常比让程序崩溃更好。
  • 函数的返回类型如何在运行时改变?

标签: c++ winapi


【解决方案1】:

从技术上讲,您不会抛出实际对象,而是抛出它的副本。这就是为什么你可以摆脱临时扔掉的原因。捕获引用也会获得对副本的引用。

如果您在 catch 块内重新抛出异常,这可能会咬到您,您可能会成为切片问题的受害者。这就是你不这样做的原因:

catch (std::exception & e)
{
    throw e;  // bad, always throws std::exception rather than what was caught
}

而是

catch (std::exception & e)
{
    throw;  // good, rethrows the exact copy that you caught without making another copy
}

附:没有规定不能从 what 返回 UTF-8 字符串。您可以将其转换为适用于 Windows I/O 的 UTF-16。标准异常类从未为 Unicode 明确设计或扩展,也没有为 Windows 添加任何非标准扩展。

【讨论】:

  • 实际上......至少在 MSVC (2005) 上,重新抛出例如throw e; 只要你通过引用就可以工作......
  • @smerlin:对于马克的第一个例子,“工作”意味着分割异常。如果它不这样做,那就是不符合 C++ 的实现。
  • @Steve:又做了一次测试,围绕rethrow的catch子句,只将异常捕获为std::exception,但调试器仍然显示了原始异常的所有信息。所以看起来编译器是符合标准的,至少在发布模式下,它完全切割了异常。
【解决方案2】:

1) 将整个程序放在 try 块中不会对性能造成任何影响,除非完全启用异常会导致性能下降

2) 没关系,因为您是按价值投掷。按值投掷意味着你投掷的任何东西在投掷时都会被复制。因此,抛出任何临时文件都是完全有效的,因为已制作了副本。

3) 据我所知,std::exception 类只能抛出char*。但是,如果您愿意,您始终可以对其进行子类化并实现对 wchar 的支持。

值得注意的是,您不应该只是main() 附近尝试一下,如果这是您的意图。

【讨论】:

    猜你喜欢
    • 2011-01-18
    • 1970-01-01
    • 2016-06-27
    • 1970-01-01
    • 2011-11-02
    相关资源
    最近更新 更多