【问题标题】:Add noexcept on otherwise-non-throwing inline functions calling C functions?在调用 C 函数的其他非抛出内联函数上添加 noexcept?
【发布时间】:2018-04-26 00:19:04
【问题描述】:

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

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

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

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

注意事项:

【问题讨论】:

标签: c++ c++11 noexcept


【解决方案1】:

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

还有一个事实是,标记函数noexcept 会明确告知您的听众该函数不会抛出。

所以是的,noexcept 是个好主意。

【讨论】:

  • 嗯,noexcept 函数也是如此。它可能仍然会抛出。但是 - 你是说 C++ 编译器将外部 C 函数视为可以 throw 吗?
  • MSVC 有标志来配置它 - 它可以假设 C 函数可以抛出。即使是纯 C 代码,GCC 也会生成异常处理信息:stackoverflow.com/questions/26300819/…
  • @einpoklum extern "C" 函数可以用 C++ 定义,然后所有 C++ 语言特性都可用。但即使extern "C" 函数是在 C 中定义的,它们也可能通过函数指针或另一个 extern "C" 函数回调到 C++ 代码中。
  • 重新编辑:抛出的noexcept 函数不是编译器错误。
【解决方案2】:

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

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

MSVC:有一个option/EHs,其中:

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

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

GCC:这是-fexceptions的文档:

启用异常处理。生成传播所需的额外代码 例外。对于某些目标,这意味着 GCC 会生成帧展开 所有功能的信息,可以产生大量数据 开销,虽然它不影响执行。如果您不指定 此选项,GCC 默认为 C++ 等语言启用它 通常需要异常处理,并为语言禁用它 像 C 通常不需要它。 但是,您可能需要 在编译需要互操作的 C 代码时启用此选项 正确使用用 C++ 编写的异常处理程序。您可能还希望 如果您正在编译不支持的旧 C++ 程序,请禁用此选项 使用异常处理。

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

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

【讨论】:

  • 如果不指定 -fexceptions 并编译 C++ 代码来调用外部 C 函数,GCC 会发生什么?
  • @einpoklum:根据我的经验,它有效。所以“您可能需要启用”部分意味着您不需要启用。但它可能会在未来发生变化。但是知道异常处理如何与 gcc 一起工作,我认为这将意味着 ABI 的变化。注意:您需要使用 -fexceptions 来编译 C 代码,而不是 C++。对于 C++,默认情况下会启用异常。
猜你喜欢
  • 1970-01-01
  • 2023-04-03
  • 2013-08-22
  • 1970-01-01
  • 2021-08-30
  • 1970-01-01
  • 2017-10-23
  • 2010-11-06
  • 1970-01-01
相关资源
最近更新 更多