【问题标题】:What is the point of `void func() throw(type)`?`void func() throw(type)` 的意义何在?
【发布时间】:2010-12-08 01:10:49
【问题描述】:

我知道这是一个有效的 c++ 程序。 函数声明中的 throw 有什么意义? AFAIK 它什么都不做,也不用于任何事情。

#include <exception>
void func() throw(std::exception) { }
int main() { return 0; }

【问题讨论】:

  • 我在 C++ 中学到但从未使用过的东西之一,我也不会使用 :)
  • "不要理会异常规范。即使是专家也不理会。他们不会按照大多数人的想法去做,而且你几乎总是不想要他们实际做的事情。"安德烈亚历山德雷斯库和赫伯萨特
  • 尽管我尊重 Sutter 和 Alexandrescu。但这是一个糟糕的建议。仅仅因为它们不好并不意味着你不应该费心去学习它们。它将帮助你解释别人为什么他们不好,让你明白为什么你实际上应该避免他们。不只是应用教条规则是一件好事。
  • 那么好 :) 我无法想象他们只是建议人们不要打扰他们。在上下文中,它可能读起来有点不同:) 干杯

标签: c++ standards throw


【解决方案1】:

它指定任何std::exception 都可以从func() 抛出,没有别的。如果抛出其他东西,它将调用unexpected() 函数,默认情况下调用terminate()

这意味着抛出其他东西几乎肯定会终止程序,就像未捕获的异常一样,但实现必须强制执行这一点。这通常与在func() 周围放置try{...}catch(){...} 块非常相似,这会抑制性能。

根据the Guru of the Week 关于它的专栏,通常情况下,异常规范是不值得的。 Boost guidelines 表示,对于非内联函数,空白 throws() 可能会有一点好处,但也有缺点。

【讨论】:

  • 最佳答案。学习者必须知道他们不应该打扰他们。
  • 我真的很喜欢这个答案并且很难选择。 Dominic 获胜是因为我通常喜欢 1-2 句带链接的答案。
【解决方案2】:

这是一个异常规范,几乎可以肯定是bad idea

它指出func 可能会抛出std::exception,而func 发出的任何其他异常都会导致调用unexpected()

【讨论】:

    【解决方案3】:

    这是一个 C++ 异常规范。它声明特定函数可能会抛出std::exception 类型。

    通常,尽管 C++ 中的异常规范被认为是要避免的特性。这是一个奇怪的特性,它的行为是在编译时声明的,但只在运行时检查(与 Java 的版本非常不同)。

    这是一篇分解功能的好文章

    【讨论】:

    • 当我开始学习 C++ 时,与 Java 的区别是让我感到困惑的地方。我到处使用它们,因为它们感觉很熟悉,然后在阅读 GOTW 后将它们全部删除。
    【解决方案4】:

    这是一个异常规范。它说 func() 可以抛出的唯一异常是 std::exception (或其派生词)。尝试抛出任何其他异常将给出 std::unexpected 。

    【讨论】:

      【解决方案5】:

      异常规范。 throw 关键字后面的类型准确地指定了函数可以抛出的所有异常(如果有)。见草案 15.4。

      注意:没有异常规范的函数允许所有异常。具有空异常规范 throw() 的函数不允许任何异常。

      【讨论】:

        【解决方案6】:

        基本上是这样的:

        void func() throw(std::exception,B) {  /* Do Stuff */}
        

        只是这个的简写:

        void func()
        {
            try
            {
                /* Do Stuff */ 
            }
            catch(std::exception const& e)
            {
                throw;
            }
            catch(B const& e)
            {
                throw;
            }
            catch(...)
            {
                unexpected();  // This calls terminate
                               // i.e. It never returns.
            }
        }
        

        调用 terminate() 很少是您想要的,因为堆栈没有展开,因此您在 RAII 中的所有努力都被浪费了。该规则的唯一例外是声明一个空的抛出列表,这主要是为了说明您支持无抛出异常保证(在这种情况下您仍应手动捕获所有异常)。

        一些重要的(恕我直言)不应该抛出的地方是析构函数和 swap() 方法。析构函数很少被显式标记为 no-throw,但 swap() 经常被标记为 no-throw。

        void myNoThrowFunc() throws()  // No-Throw (Mainlly for doc purposes).
        {
            try
            {
                /* Do Stuff */
            }
            catch(...)  // Make sure it does not throw.
            {
                /* Log and/or do cleanup */
            }
        }
        

        【讨论】:

          猜你喜欢
          • 2017-06-07
          • 1970-01-01
          • 2011-09-10
          • 2010-11-12
          • 1970-01-01
          • 2020-08-27
          • 2011-04-12
          相关资源
          最近更新 更多