从C ++ 11中的std :: exception派生时的异常规范

时间:2010-11-26 04:44:13

标签: c++ gcc c++11 exception-specification

我有一个例外类如下:

#include <exception>

struct InvalidPathException : public std::exception
{
   explicit InvalidPathException() {}
   const char* what() const;
};

const char*
InvalidPathException::what() const {
    return "Path is not valid";
}

使用-Wall -std = c ++ 0x

在GCC 4.4下编译时
  

错误:looser throw说明符   &#39;虚拟常量字符*   InvalidPathException :: what()const&#39;

     

错误:覆盖&#39;虚拟const char *   std :: exception :: what()const throw()&#39;

非常正确,因为我覆盖了确实拥有std::exception异常说明符的what() throw()方法。但通常be informed,我们不应该使用异常说明符。据我了解,它们是deprecated in C++11,但显然还没有在GCC中使用-std = c ++ 0x。

所以我现在对最好的方法感兴趣。在我开发的代码中,我确实关心性能,因此担心throw()经常提到的开销,但实际上这个开销是如此严重?我是否正确地认为我只在实际调用what()时遭受它,这只会在抛出这样的异常之后(同样对于从std :: exception继承的其他方法都有throw()说明符)?

或者,有没有办法解决GCC给出的这个错误?

1 个答案:

答案 0 :(得分:7)

throw规范很有用,因为它们实际上在调用者的站点上启用了编译器优化,因为Wikipedia知道(我没有方便的技术报告)。

出于优化机会的原因,在即将推出的标准中,nothrow-specifications not 已弃用,它们只是看起来不再是throw (),而是被称为noexcept 。嗯,是的,他们的工作方式略有不同。

Here是对noexcept的讨论,该讨论还详细说明了为什么传统的nothrow规范在竞争对手的网站上进行了规范性的优化。

通常,您需要为每个throw规范付费,至少使用完全兼容的编译器,GCC在这方面看起来并不总是如此。那些throw规范必须在运行时检查,甚至是空的。这是因为如果引发的异常不符合throw规范,则必须在该堆栈帧内进行堆栈展开(因此除了一致性检查之外还需要代码)然后{{1必须被调用。另一方面,您可能会为每个 std::unexpected规范节省时间/空间,因为编译器在调用该函数时可能会做出更多假设。我说,只有一个分析器可以给你一个明确的答案,你的特定代码是否受到(!)throw规范的影响或改进。

作为解决实际问题的方法,可以进行以下工作吗?

  • 介绍throws并将其用于您的例外#define NOTHROW throw ()和其他内容。
  • 当GCC实施what时,重新定义noexcept

更新

@James McNellis指出,NOTHROW将向前兼容。在这种情况下,我建议您只使用throw (),除此之外,如果有疑问,请使用个人资料。