繁体   English   中英

内联函数和一个定义规则

[英]inline functions and the one definition rule

inline函数提供了一个定义规则的弱化 - 允许多个定义,尽管有一些限制。 我在网上发现的一个措辞是

要求是每个定义应该相同,这意味着它应该由相同的标记组成并引用相同的项目。

虽然我承认我不知道这是否是确定的。 我也不确定它有多严格。

我正在考虑使用class定义和/或inline函数创建标题的情况,我希望它是#include -able,无论是在C ++ 03,C ++ 11中编译,还是在以后的某些标准中编译。 使用__cplusplus宏来有条件地更改代码是很自然的,但是ODR会发挥作用吗? 例如, 条件似乎是合理的:

  • 提供嵌套的typedef
  • 提供一个嵌套class
  • 提供与移动相关的功能。
  • 标记函数throw()noexcept (这一点特别重要,因为每个析构函数noexcept在C ++ 11中获取一个隐式的noexcept 。)
  • 标记功能constexpr
  • override和/或final标记一个函数。
  • 标记函数[[noreturn]]和/或[[nodiscard]]
  • 标记参数[[maybe_unused]]
  • 在函数体中使用[[fallthrough]]

但是,如果有人想要启用#include这些头文件库以便在不同标准下编译并仍然可以安全地一起使用,那么这些中的哪一个 - 如果有的话 - 实际上是允许的?

一般来说,你不能安全地做这些事情。 安全使用说两种类的定义只有两种方法。 平凡的是,你可以简单地编译两个不同的进程,通过例如共享内存进行通信。 不那么简单,如果出现以下情况,您可以使用两个以两种不同方式定义相同符号A的库:

  • 符号A只是库的实现细节; 它不能由库提供,也不能出现在任何接口中
  • 沿着这些方向,库的头文件都不应该传递包含A的头。 因此,客户端翻译单元将不会从库中接收任何A的定义。
  • 符号A的可见性必须标记为私有/隐藏。

如果你做了所有这些,那么A确实是库的实现细节,你可以使用多个不同定义A的库。 如果其中任何一个不满意,那么你不能保证上述任何一个都可以工作(虽然有些人会这样做)。

对于不熟悉链接器的人来说,最令人惊讶的结果之一是,如果lib1和lib2都使用符号A,即使它们阻止通过头部的任何泄漏,如果A的可见性是公开的,那么A的单个定义将是用于两个库。 因此lib2将使用lib1的定义,反之亦然。 这很容易导致UB。

在* nix系统上,公共可见性是默认设置,因此您需要确保隐藏符号,这有点神秘。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM