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

Add noexcept on otherwise-non-throwing inline functions calling C functions?

本文关键字:函数 添加 noexcept 调用      更新时间:2023-10-16

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

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

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

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

注:

  • 我应该对明显不能抛出的简单函数使用noexcept吗?,在这种情况下,编译器不知道函数是否可以抛出;对于C函数,它确实知道
  • 更普遍的问题是,我什么时候才能真正使用noexcept?有可能相互矛盾的答案,此外,公认的答案来自5年前,并表示"现在说还为时过早">

即使wrapped_lib_fooextern "C"函数,编译器也无法知道堆栈中的某个地方wrapped_lib_foo从不抛出,除非您明确告诉它。

还有一个事实是,标记函数noexcept明确地通知受众该函数不会抛出。

所以noexcept是个好主意。

当您知道函数不会抛出时,我认为添加"noexcept"是一种很好的做法。这是因为如果C函数回调到C++中,它可以抛出。

是否允许这种对C++和throw的调用,似乎取决于编译器。我检查了两个编译器:

MSVC:有一个选项/EHs,它是

只捕获C++异常的异常处理模型告诉编译器假设声明为外部"C"的函数可能抛出异常。

因此,如果指定了此选项,则编译器假设C函数可以抛出。

GCC:以下是-fexceptions:的文档

启用异常处理。生成传播所需的额外代码例外情况。对于某些目标,这意味着GCC生成框架展开所有函数的信息,可以产生显著的数据大小开销,尽管它不会影响执行。如果未指定该选项,GCC默认情况下为C++等语言启用通常需要异常处理,并针对语言禁用它比如C,通常不需要它。但是,您可能需要在编译需要互操作的C代码时启用此选项正确使用用C++编写的异常处理程序。您也可以如果您正在编译没有使用异常处理。

因此,这意味着使用-fexceptions,GCC编译可以抛出的C代码。但是,请注意:当调用C函数时,编译器不知道C代码是否使用-fexceptions编译。所以它不得不假设,事实确实如此。因此,GCC似乎必须假设C代码可以抛出(另一种可能的方式是,需要为C++代码指定-fexception,以告诉编译器被调用的C代码可以引发,但-fexceptions的doc没有这样说)。

注意:对于GCC,即使当前没有使用-fexceptions编译的C代码,从调用堆栈抛出(其中涉及C函数)也能工作。