我们应该提供一个没有抛出说明符的析构函数吗?

q09*_*987 8 c++ destructor exception throw specifier

namespace QuantLib {

    //! Base error class
    class Error : public std::exception {
      public:
        /*! The explicit use of this constructor is not advised.
            Use the QL_FAIL macro instead.
        */
        Error(const std::string& file,
              long line,
              const std::string& functionName,
              const std::string& message = "");
        /*! the automatically generated destructor would
            not have the throw specifier.
        */
        ~Error() throw() {}
        //! returns the error message.
        const char* what() const throw ();
      private:
        boost::shared_ptr<std::string> message_;
    };

}
Run Code Online (Sandbox Code Playgroud)

正如您在注释中看到的那样,类的析构函数Error显式提供了一个带有no-throw说明符的空实现.

问题:这有必要吗?或者这是一个很好的做法,比较让编译器生成隐式析构函数?

Dav*_*eas 9

在C++ 11中,析构函数是隐式的throw()(除非该类型的任何成员或基类具有带有不同异常规范的析构函数),因此如果您在C++ 11模式下进行编译则没有必要.

如果你在C++ 03中,你可能想要添加它,但是它是否会产生效果是非常实现的定义...现在,为了文档目的你可能想要添加它,但同样,它通常是假设析构函数不抛出.

  • 几个星期前,我和一位同事一起讨论了这部分标准,问题是异常规范(如果没有为析构函数提供)将是一个隐式声明的析构函数,它反过来又是一个联合体析构函数的*隐式定义*将调用的所有函数的异常规范,它们是所有成员和基础的析构函数.我们当时的理解是`~Error(){throw 1; F(); 即使`f`抛出,``也会有一个'noexcept(true)`异常规范... (4认同)
  • ...另请注意,在*this*析构函数中运行的实际代码不会影响异常规范,因为单独的编译模型意味着不同的转换单元可能只能看到析构函数的声明,因此该析构函数的定义不能用来改变声明.[@JerryCoffin - 在这里添加,我忘了把它添加到第一个评论答案] (4认同)
  • ......这是一个重要的突破性变化,因为除非你在这种情况下明确要求"noexcept(false)",否则你的程序会破坏契约(现在隐含的是"noexcept(true)" - )除非其中一个基地或成员有不同的例外规范).虽然我的措辞不是100%精确,但事实是,如果你可以在你的析构函数中添加一个`noexcept`(即它不抛出),那么不编写异常规范将提供相同的最终结果:`noexcept` . (3认同)

Oli*_*rth 5

应始终将析构函数设计为永不抛出异常.所以从这个意义上来说,仅仅为了将其标记为无抛出而声明空的析构函数几乎没有意义.