从C ++ 11中的std :: exception派生时的异常规范 [英] Exception specifications when deriving from std::exception in C++11

查看:1219
本文介绍了从C ++ 11中的std :: exception派生时的异常规范的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个异常类如下:

  #include< exception> 

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

const char *
InvalidPathException :: what()const {
return路径无效;
}



当在GCC 4.4下使用-Wall -std = c ++ 0x


错误:
的looser throw说明符virtual const char *
InvalidPathException :: what()const' p>

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




非常正确,因为我重写 std :: exception what() 方法,确实有一个 throw()异常说明符。但由于通常会通知,我们不应使用异常说明符。根据我的理解,他们是在C ++ 11中弃用,但显然尚未在GCC中使用-std = c ++ 0x。



所以我现在对最好的方法感兴趣。在我开发的代码中,我关心性能,所以担心 throw()的开销,但实际上这个开销是如此严重吗?我的想法是,我只会忍受当 what()实际上被调用,这将只是在这样的异常抛出后(同样对于其他方法继承自std :: exception,它们都具有 throw()说明符)?



解决方案

清空 throw 规格是由GCC提供的。

维基百科知道(我没有技术



出于优化机会的原因,在后续标准中不允许不再使用标准,它们只是不显示像 throw(),但被称为 noexcept 。噢,是的,他们的工作方式略有不同。



这里 noexcept 的讨论,也详细说明了为什么传统的nothrow规范prohobit优化在被调用的网站。 >

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



以下工作可以解决您的实际问题:




  • 介绍 #define NOTHROW throw()并将其用于您的异常 what 和其他东西。

  • 当GCC实现 noexcept 时,重新定义 NOTHROW



    • 更新



      正如@James McNellis所说, throw()将向前兼容。在这种情况下,我建议只要使用 throw(),除非有疑问,否则请使用配置文件。


      I have an exception class as follows:

      #include <exception>
      
      struct InvalidPathException : public std::exception
      {
         explicit InvalidPathException() {}
         const char* what() const;
      };
      
      const char*
      InvalidPathException::what() const {
          return "Path is not valid";
      }
      

      When compiling under GCC 4.4 with -Wall -std=c++0x

      error: looser throw specifier for 'virtual const char* InvalidPathException::what() const'

      error: overriding 'virtual const char* std::exception::what() const throw ()'

      Quite right, too, since I'm overriding std::exception's what() method that does indeed have a throw() exception specifier. But as one will often be informed, we shouldn't use exception specifiers. And as I understand it, they are deprecated in C++11, but evidently not yet in GCC with -std=c++0x.

      So I'd be interested in the best approach for now. In the code I'm developing I do care about performance and so worry about the oft-mentioned overhead of throw(), but in reality is this overhead so severe? Am I right in thinking that I'd only suffer it when what() is actually called, which would only be after such an exception is thrown (and likewise for the other methods inherited from std::exception that all have throw() specifiers)?

      Alternatively, is there a way to work around this error given by GCC?

      解决方案

      Empty throw specifications are useful, as they actually enable compiler optimizations at the caller's site, as Wikipedia knows (I don't have a technical quote handy).

      And for reasons of optimization opportunities, nothrow-specifications are not deprecated in the upcoming standard, they just don't look like throw () any more but are called noexcept. Well, yes, and they work slightly differently.

      Here's a discussion of noexcept that also details why traditional nothrow-specifications prohobit optimizations at the callee's site.

      Generally, you pay for every throw specification you have, at least with a fully compliant compiler, which GCC has, in this respect, appearantly not always been. Those throw specifications have to be checked at run-time, even empty ones. That is because if an exception is raised that does not conform to the throw specification, stack unwinding has to take place within that stack frame (so you need code for that in addition to the conformance check) and then std::unexpected has to be called. On the other hand, you potentially save time/space for every empty throw specification as the compiler may make more assumptions when calling that function. I chicken out by saying only a profiler can give you the definitive answer of whether your particular code suffers from or improves by (empty!) throws specification.

      As a workaround to your actual problem, may the following work?

      • Introduce #define NOTHROW throw () and use it for your exception's what and other stuff.
      • When GCC implements noexcept, redefine NOTHROW.

      Update

      As @James McNellis notes, throw () will be forward-compatible. In that case, I suggest just using throw () where you have to and, apart from that, if in doubt, profile.

      这篇关于从C ++ 11中的std :: exception派生时的异常规范的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆