c++ - 激发 'inline' 说明符的现实世界示例?

标签 c++ c++17

背景:C++ inline 关键字并不能确定函数是否应该内联。

相反,内联允许您提供单个函数或变量的多个定义,只要每个定义出现在不同的翻译单元中即可。

基本上,这允许在头文件中定义全局变量和函数。

有一些例子可以说明为什么我可能想在头文件中编写定义吗?

我听说可能存在无法将定义写入单独的 cpp 文件的模板示例。

我听说过其他有关性能的说法。但这真的是真的吗?据我所知,使用 inline 关键字并不能保证函数调用是内联的(反之亦然)。

我有一种感觉,这个功能可能主要由试图编写古怪且高度优化的实现的库编写者使用。但有一些例子吗?

最佳答案

这实际上很简单:当您想在 header 中编写(函数或变量 (C++17 起))的定义时,您需要内联。否则你就会违反odr一旦您的 header 包含在超过 1 tu 中, 。就是这样。这就是全部内容。

值得注意的是,某些实体是隐式声明为内联的,例如:

  • 在类体内定义的方法
  • 模板函数和变量
  • constexpr 函数和变量

现在的问题是为什么以及何时有人想要在 header 中编写定义,而不是分隔 header 中的声明和源代码文件中的定义。这种方法有优点也有缺点。以下是一些需要考虑的因素:

优化

将定义放在源文件中意味着该函数的代码被烘焙到 tu 二进制文件中。它不能在定义它的 tu 之外的调用位置内联。将其放在 header 中意味着编译器可以将其内联到它认为合适的任何地方。或者它可以根据调用该函数的上下文为该函数生成不同的代码。使用lto也可以实现同样的效果。在可执行文件或库中,但对于库来说,启用此优化的唯一选项是在 header 中包含定义。

库分发

除了在库中启用更多优化之外,拥有仅 header 的库(如果可能)意味着更简单的方式来分发该库。用户所要做的就是下载 headers 文件夹并将其添加到他/她的项目的包含路径中。在非 header 库的情况下,事情变得更加复杂。因为您不能混合和匹配由不同编译器甚至由相同编译器但具有不同标志编译的二进制文件。因此,您要么必须将完整的源代码与构建工具一起分发您的库,要么以多种格式编译该库(CPU 架构/操作系统/编译器/编译器标志组合)

人类偏好

一些人(包括我)认为必须编写一次代码是一个优势:无论是从代码文档的角度还是从维护的角度来看。其他人认为将声明与定义分开更好。一个论点是它实现了接口(interface)与实现的分离,但事实并非如此:在 header 中,您需要有私有(private)成员声明,​​即使它们不是接口(interface)的一部分。

编译时性能

将所有代码放在 header 中意味着在每个 tu.c 文件中重复它。当涉及到编译时间时,这是一个真正的问题。重 header C++ 项目因编译速度慢而臭名昭著。它还意味着对函数定义的修改将触发包含该函数定义的所有 tu 的重新编译,而不是在源代码中定义的情况下仅触发 1 个 tu。 Precompiled headers尝试解决这个问题,但解决方案不可移植并且有自己的问题。

关于c++ - 激发 'inline' 说明符的现实世界示例?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62927939/

相关文章:

C++:应用复合模式

c++ - 关于C++字符串的问题

c++ - 为什么 C++ 分配器要求不要求 construct() 构造 value_type 的对象?

c++ - c-style this 或 shared_from_this 作为函数参数

c++ - 在 constexpr-if 条件下比较 constexpr 函数参数导致错误

c++ - qt中GUI同时更新和控制

c++ - C++ 中构造函数可能存在歧义

c++ - 如何使std::filesystem::directory_iterator依次列出文件名

c++ - 关于在模板中使用可变参数的逻辑运算符

c - 如何找到正确的括号顺序?