当前位置: 首页 > 知识库问答 >
问题:

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

胥玮
2023-03-14

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

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

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

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

注意事项:

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

共有2个答案

郑宜民
2023-03-14

我认为这是添加“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 函数的调用堆栈中抛出也可以工作。

芮叶秋
2023-03-14

即使wrapped_lib_foo是一个extern"C"函数,编译器也无法知道堆栈下的某个地方wrapped_lib_foo永远不会抛出,除非你明确地告诉它。

还有一个事实是,将函数标记为< code>noexcept明确地告诉您的读者,该函数不抛出。

所以yes<code>noexcept</code>是个好主意。

 类似资料:
  • 函数是一个可以重复使用的代码块,CPU 会一条一条地挨着执行其中的代码。CPU 在执行主调函数代码时如果遇到了被调函数,主调函数就会暂停,CPU 转而执行被调函数的代码;被调函数执行完毕后再返回到主调函数,主调函数根据刚才的状态继续往下执行。 一个 C/ C++ 程序的执行过程可以认为是多个函数之间的相互调用过程,它们形成了一个或简单或复杂的调用链条,这个链条的起点是 main(),终点也是 ma

  • C++ 类 & 对象 C++ 内联函数是通常与类一起使用。如果一个函数是内联的,那么在编译时,编译器会把该函数的代码副本放置在每个调用该函数的地方。 对内联函数进行任何修改,都需要重新编译函数的所有客户端,因为编译器需要重新更换一次所有的代码,否则将会继续使用旧的函数。 如果想把一个函数定义为内联函数,则需要在函数名前面放置关键字 inline,在调用函数之前需要对函数进行定义。如果已定义的函数多

  • 我正在尝试通过与分支内联的am调用c中的外部函数。我正在编译为arm m0指令集,但它返回错误表达式。 代码是: 回报是: 我们需要做什么?

  • 简而言之:我想创建一个类型为的泛型类,它应该调用一个类型为的具体化内联函数,以便能够更通用地使用Gson 但是我希望我的其他类通过某个类实例调用这个函数。例如,类似于应该返回列表,而不是直接调用。我如何实现这样的功能?

  • 问题 当你编写使用回调函数的代码的时候,担心很多小函数的扩张可能会弄乱程序控制流。 你希望找到某个方法来让代码看上去更像是一个普通的执行序列。 解决方案 通过使用生成器和协程可以使得回调函数内联在某个函数中。 为了演示说明,假设你有如下所示的一个执行某种计算任务然后调用一个回调函数的函数(参考7.10小节): def apply_async(func, args, *, callback):

  • 我正在尝试编译以下C代码(另存为example4.cpp) 此代码给出以下错误: example4.cpp:在函数'Conconexpr double nth(double, int)':example4.cpp:24: 9: error:调用非Conconexpr函数'std::basic_ostream 谁能推荐一下吗? 谢谢你。