我已经为一些C库实现了C绑定。库API调用可以失败,但显然不能抛出任何东西;对于这个问题,我的绑定都是内联的。
现在,编译器可以弄清楚,对于我的大多数内联函数/方法,不能抛出异常;例如,假设我有:
bool foo() {
auto result = wrapped_lib_foo();
return some_constexpr_nothrow_cond(result);
}
我应该用noexcept
标记这样的函数/方法吗?
注意事项:
即使wrapped_lib_foo
是一个extern"C"
函数,编译器也无法知道堆栈下的某个地方wrapped_lib_foo
永远不会抛出,除非你明确地告诉它。
还有一个事实是,将函数标记为< code>noexcept明确地告诉您的读者,该函数不抛出。
所以yes<code>noexcept</code>是个好主意。
我认为这是添加“noexexcept ”的好习惯,当您知道一个函数不会抛出时。这是因为 C 函数如果回调到 C 中,可能会抛出。
是否允许这种回调 C 并抛出,似乎取决于编译器。我已经检查了两个编译器:
MSVC:有一个选项 /EHs
,它:
异常处理模型只捕捉C异常,并告诉编译器假设声明为extern“C”的函数可能会抛出异常。
因此,如果指定了此选项,则编译器假定 C 函数可以抛出。
GCC:这是< code>-fexceptions的文档:
启用异常处理。生成传播异常所需的额外代码。对于某些目标,这意味着GCC为所有函数生成帧展开信息,这可能会产生大量的数据大小开销,尽管它不会影响执行。如果未指定此选项,GCC 将默认为通常需要异常处理的 C 等语言启用此选项,并为通常不需要此选项的 C 等语言禁用此选项。但是,在编译需要与用 C 编写的异常处理程序正确互操作的 C 代码时,您可能需要启用此选项。如果您正在编译不使用异常处理的旧 C 程序,您可能还希望禁用此选项。
因此,这意味着通过< code>-fexceptions,GCC编译C代码,这些代码可以抛出。但是请注意:当调用C函数时,编译器不知道C代码是否是用< code>-fexceptions编译的。所以它必须假设,它是。因此,GCC似乎必须假设C代码可以抛出(另一种可能的方式是,需要为C代码指定< code >-Fe exception 来告诉编译器被调用的C代码可以抛出,但是< code >-Fe exceptions 的doc并没有这样说)。
注意:对于 GCC,即使当前没有使用 -fexceptions
编译的 C 代码,从涉及 C 函数的调用堆栈中抛出也可以工作。