【问题标题】:C++ exception, undefined behavior and noexceptC++ 异常、未定义行为和 noexcept
【发布时间】:2016-06-11 05:33:02
【问题描述】:
关于这个功能
int test(int a,int b)
{
return a/b;
}
如果我打电话给test(2,1),什么都不会发生。
但是如果我打电话给test(2,0),它会导致未定义的行为。
结果,我应该将其定义为noexcept吗?
顺便说一句,为什么std::vector::operator[] 不是noexcept?
【问题讨论】:
标签:
c++
exception
undefined-behavior
noexcept
【解决方案1】:
我应该将其定义为noexcept吗?
如果你愿意,你当然可以。确实,该函数不会引发异常。但是,它仍然可能因被零除而失败。
这取决于你认为noexcept 应该是什么意思。标准库似乎将其视为关键字,这意味着该函数不可能失败,而不仅仅是它不会抛出。如果您遵循他们的约定,则不应使用noexcept。但是,如果您希望 noexcept 仅表示它不会抛出,那么您应该这样做。
无论哪种方式,您都应该始终使用相同的约定。除了构造函数和赋值运算符之外,这两种方法都没有太大的好处。
【解决方案2】:
您实际上是以错误的方式问这个问题。使用 noexcept 的决定通常应该是自上而下的(例如,这样做对函数的调用者是否重要)而不是自下而上(即基于您的函数正在执行的操作)。
指定“不得扔”与“不得扔”是有区别的。 noexcept 适用于“不得扔”的情况,不适用于“不得扔”。但决定哪个合适取决于函数调用者的需求,而不是函数的实现方式。
通过省略noexcept,允许提供函数的抛出版本,例如用于调试目的。 “不需要抛出”类别中的函数可以在调试期间安全地替换为抛出版本,然后在“发布”构建中使用非抛出版本。此类检查在“发布”版本中是不可取的,因为它们通常会对程序性能指标产生不利影响 - 并且在某些情况下还会导致不需要的副作用(例如,如果检查执行诸如探测调用堆栈或跟踪总内存使用程序)。
这就是 operator[] for std::vector 不是 nothrow 的原因 - 它没有被指定为 throwing,但用 throwing 版本替换它可能有助于调试目的。如果将其指定为nothrow,则会减少开发人员在发布之前对其代码(使用标准库)进行调试的机会。