9

我有一个异常类如下:

#include <exception>

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

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

在 GCC 4.4 下使用 -Wall -std=c++0x 编译时

错误:'virtual const char* InvalidPathException::what() const' 的更宽松的抛出说明符

错误:覆盖 'virtual const char* std::exception::what() const throw ()'

也非常正确,因为我正在覆盖确实具有异常说明符std::exception的 's方法。但正如人们经常被告知的那样,我们不应该使用异常说明符。据我了解,它们在 C++11 中已被弃用,但显然尚未在带有 -std=c++0x 的 GCC 中。what()throw()

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

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

4

1 回答 1

7

throw规范很有用,因为它们实际上在调用者的站点上启用了编译器优化,正如Wikipedia所知(我手边没有技术报价)。

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

这里的讨论noexcept还详细说明了为什么传统的 nothrow 规范禁止在被调用方站点进行优化。

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

作为您实际问题的解决方法,以下方法是否可行?

  • 介绍#define NOTHROW throw ()它并将其用于您的异常what和其他内容。
  • 当 GCC 实现noexcept时,重新定义NOTHROW.

更新

正如@James McNellis 所指出的,throw ()它将是向前兼容的。在这种情况下,我建议只使用throw ()您必须使用的位置,除此之外,如果有疑问,请使用配置文件。

于 2010-11-26T04:59:59.460 回答