C++ 异常、未定义行为和 noexcept
C++ exception, undefined behavior and noexcept
关于此功能
int test(int a,int b)
{
return a/b;
}
如果我调用 test(2,1)
,什么也不会发生。
但是如果我调用 test(2,0)
,它会导致未定义的行为。
因此,我应该将其定义为 noexcept
?
顺便说一句,为什么 std::vector::operator[]
不是 noexcept
?
Should I define it as noexcept
?
当然可以,只要你愿意。的确,该函数不会抛出异常。但是,它仍然可能因被零除而失败。
这取决于您认为 noexcept
应该是什么意思。标准库似乎将其视为关键字,这意味着该函数不可能失败,而不仅仅是它不会抛出。如果你按照他们的惯例,你不应该做到 noexcept
。但是,如果您希望 noexcept
仅表示它不抛出,那么您应该这样做。
无论哪种方式,您都应该始终使用相同的约定。除了构造函数和赋值运算符之外,这两种方法都没有太大的好处。
你问这个问题的方式其实是错误的。使用 noexcept
的决定通常应该是自上而下的(例如,这样做对你的函数的调用者来说是否重要)而不是自下而上的(即基于你的函数正在做什么)。
指定某物 "must not throw" 与 "need not throw" 之间存在差异。 noexcept
适用于 "must never throw",不适用于 "need not throw"。但决定哪个合适取决于函数调用者的需求,而不是函数的实现方式。
通过省略 noexcept
,可以提供函数的抛出版本,例如,调试目的。 "need not throw" 类别中的函数可以在调试期间安全地替换为抛出版本,然后在 "release" 构建中使用非抛出版本。这种检查在 "release" 构建中是不可取的,因为它们通常会对程序性能指标产生不利影响 - 并且在某些情况下还会导致不需要的副作用(例如,如果检查执行诸如探查调用堆栈或跟踪总内存使用量之类的事情程序)。
这就是 std::vector
的 operator[]
不是 nothrow
的原因 - 它未指定为抛出,但用抛出版本替换它可能有助于调试目的。如果它被指定为 nothrow
,这将减少开发人员在发布之前调试他们的代码(使用标准库)的机会。
关于此功能
int test(int a,int b)
{
return a/b;
}
如果我调用 test(2,1)
,什么也不会发生。
但是如果我调用 test(2,0)
,它会导致未定义的行为。
因此,我应该将其定义为 noexcept
?
顺便说一句,为什么 std::vector::operator[]
不是 noexcept
?
Should I define it as
noexcept
?
当然可以,只要你愿意。的确,该函数不会抛出异常。但是,它仍然可能因被零除而失败。
这取决于您认为 noexcept
应该是什么意思。标准库似乎将其视为关键字,这意味着该函数不可能失败,而不仅仅是它不会抛出。如果你按照他们的惯例,你不应该做到 noexcept
。但是,如果您希望 noexcept
仅表示它不抛出,那么您应该这样做。
无论哪种方式,您都应该始终使用相同的约定。除了构造函数和赋值运算符之外,这两种方法都没有太大的好处。
你问这个问题的方式其实是错误的。使用 noexcept
的决定通常应该是自上而下的(例如,这样做对你的函数的调用者来说是否重要)而不是自下而上的(即基于你的函数正在做什么)。
指定某物 "must not throw" 与 "need not throw" 之间存在差异。 noexcept
适用于 "must never throw",不适用于 "need not throw"。但决定哪个合适取决于函数调用者的需求,而不是函数的实现方式。
通过省略 noexcept
,可以提供函数的抛出版本,例如,调试目的。 "need not throw" 类别中的函数可以在调试期间安全地替换为抛出版本,然后在 "release" 构建中使用非抛出版本。这种检查在 "release" 构建中是不可取的,因为它们通常会对程序性能指标产生不利影响 - 并且在某些情况下还会导致不需要的副作用(例如,如果检查执行诸如探查调用堆栈或跟踪总内存使用量之类的事情程序)。
这就是 std::vector
的 operator[]
不是 nothrow
的原因 - 它未指定为抛出,但用抛出版本替换它可能有助于调试目的。如果它被指定为 nothrow
,这将减少开发人员在发布之前调试他们的代码(使用标准库)的机会。