【问题标题】:Function try blocks, but not in constructors函数尝试块,但不在构造函数中
【发布时间】:2011-04-22 20:00:44
【问题描述】:

只是一个简单的问题。有什么区别

void f(Foo x) try
{
   ...
}
catch(exception& e)
{
   ...
}

void f(Foo x)
{
    try { ... }
    catch (exception& e)
    {
        ...
    }
}

?

如果不是,为什么函数 try 块用于(构造函数的初始化列表被搁置的情况)?如果x 传递给fFoo 的复制构造函数抛出异常会怎样?

【问题讨论】:

    标签: c++ exception-handling


    【解决方案1】:

    函数 try 块只在构造函数中需要。在所有其他情况下,通过将整个函数体包含在一个普通的 try/catch 块中,可以达到完全相同的效果。

    如果用于初始化参数的复制构造函数抛出异常,则会发生在函数调用之前。它不能被函数 try 块或函数中的异常处理程序捕获,因为函数没有被调用。

    【讨论】:

    • 这意味着非构造函数的函数 try 块只是一种替代语法,没有语义目的,这可能确实是它们存在的一个有争议的论据。另一方面,C++中有太多莫名其妙的东西,甚至在那些与兼容性无关的东西中也是如此。
    【解决方案2】:

    有些事情是允许的,因为禁止它们会更难。允许在一些函数体上使用函数 try 块,但并非所有函数体都会使语法和编译器更加复杂。

    【讨论】:

      【解决方案3】:

      刚刚在Dr. Dobb's article 中发现了一个有趣的点(虽然很老):

      ...请记住,您不能在 function-try-block 处理程序中返回值。所以对非空函数使用函数try块是没有意义的

      这是他们的代码示例:

      int f()
      try
      {
         ...
      }
      catch(Error &e)
      {
         // oops, can't return int from here!
      }
      

      这实际上意味着函数 try 块比“常规” try 块,除了在构造函数中之外,不鼓励使用它们。

      (这篇文章是 2000 年的,所以如果有人能评论一下这在当前标准中是否仍然如此,那就太好了)

      【讨论】:

      • ...除非“catch”块本身无条件地抛出或重新抛出,在这种情况下,函数 try 块是写这个的最干净的方法,IMO。
      • (5 年后添加评论:)我用 gcc 5.4 进行了测试——在那里,我可以从 catch-block 返回一个值。但是,我没有研究任何标准。
      • 这个答案是错误的,AFAIK 在创建时就已经如此了,请参阅here,尤其是底部的示例。
      • 我测试了我们是否可以从非 void 函数上的函数 try 块的 catch 处理程序返回;我以前可以。但根据 cppreference 条目,这是未定义的行为。
      【解决方案4】:

      为了在构造函数初始化列表中捕获异常而明确添加了函数尝试块。

      在您的示例中,没有构造函数初始化,因此两种形式之间没有区别。

      【讨论】:

      • 这并不能解决可能在构造函数中抛出的静态/全局对象的问题,因为无论如何都会重新抛出异常。
      • @Armen:如果对象无法初始化,构造函数必须抛出。这是报告构造失败的唯一方式。
      猜你喜欢
      • 2015-03-11
      • 2015-03-09
      • 2020-06-19
      • 2015-10-07
      • 2013-11-10
      • 2018-08-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多