提问者:小点点

在调用C函数的非抛出内联函数上添加noexcept?


我已经为一些C库实现了C绑定。库API调用可以失败,但显然不能抛出任何东西;对于这个问题,我的绑定都是内联的。

现在,编译器可以弄清楚,对于我的大多数内联函数/方法,不能抛出异常;例如,假设我有:

bool foo() { 
    auto result = wrapped_lib_foo(); 
    return some_constexpr_nothrow_cond(result); 
}

我应该用noexcept标记这样的函数/方法吗?

注意事项:

  • 不是我应该使用no的欺骗,除了显然不能抛出的简单函数?,因为在这种情况下,编译器不知道函数是否可以抛出;对于C函数 - 它确实知道。
  • 更普遍的问题 我什么时候应该真正使用 noexcept? 有潜在的相互矛盾的答案,此外,公认的答案来自 5 年前,并说“现在说还为时过早”。

共2个答案

匿名用户

即使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 函数的调用堆栈中抛出也可以工作。