使用noexcept和编译器标志来关闭异常

时间:2018-04-11 10:43:48

标签: c++

介绍

在嵌入式c ++中,特别是在实时系统中,不需要处理异常,如果系统崩溃,通常情况下,我们会让它崩溃。每次崩溃都是程序员错误,必须修复。因此,无需在发布中处理异常。

问题

使用noexcept说明符可以显着减少二进制文件的大小并提高性能。这样,stl函数内的每个noexcept函数都会调用noexcept(如果可用)。但是这个说明符的使用是限制性的,并且有很多限制(继承,虚函数签名,兼容性)。如果在没有正确集成的情况下修改源代码,则会出现looser throw specifier for...等错误。

没有异常标志(如g ++ -fno-exceptions)仅替换throw的所有abort,并且可能会减少一些堆栈大小。

问题

在需要升级遗留代码(在c ++ 11之前),提高性能和减少二进制文件大小的情况下,是否有任何良好实践如何使用noexcept说明符或标志?现在,我只能看到一种方法 - 为每个函数添加noexcept

编译器(arm-none-eabi-g ++,C ++编译器MSVC),c ++ 14

1 个答案:

答案 0 :(得分:4)

  

这样,noexcept函数内的每个stl函数都会调用noexcept重载(如果可用)。

不,因为您无法在noexcept上超载。使用noexcept标记函数不会影响它调用的函数的重载解析。

标记函数noexcept的大小减少是因为编译器不需要为堆栈展开和异常处理发出代码,它只能终止。但是如果使用-fno-exceptions,编译器也不必为堆栈展开和异常处理发出代码,因此您应该获得相同的好处(无需在任何地方添加noexcept)。

  

如果需要升级遗留代码(在c ++ 11之前),提高性能并减少二进制文件的大小,是否有任何良好实践如何使用noexcept说明符或标志?

好的做法是只将noexcept添加到您知道肯定无法抛出的函数中,并且永远不会更改为如果您确实希望他们在发生异常时调用std::terminate

这并不意味着将其添加到每个功能中。

这并不意味着不小心将其添加到虚拟功能中。这样做会更改基类的合同,并且需要更新所有覆盖。