c++ - 如果编译器可以自行内联函数,为什么内联函数必须在 header 中为 "defined"

标签 c++ function optimization compilation inline

我们必须在 header 中定义内联函数的原因是调用该函数的每个编译单元都必须具有完整的定义才能替换调用或替换它。我的问题是,如果编译器可以并且确实进行了自己的内联优化,为什么我们被迫将定义放在头文件中,这将要求它深入研究定义函数的 cpp 文件。

换句话说,编译器在我看来有能力在头文件中看到函数“声明”,转到相应的 cpp 文件并从中提取定义并将其粘贴到另一个文件中的适当位置cpp。鉴于这种情况,为什么坚持在 header 中定义函数,暗示编译器似乎无法“看到”其他 cpp 文件。

MSDN 关于 Ob2/优化设置的说法:

Ob2/ The default value. Allows expansion of functions marked as inline, __inline, or __forceinline, and any other function that the compiler chooses (My emphasis).

最佳答案

我们被迫在头文件中提供内联函数定义的原因(或者至少,在给定编译单元中内联函数时,以实现可见的某种形式)是 C++ 标准的要求。

但是,该标准并没有特意阻止实现(例如工具链或其部分,例如预处理器、编译器本身、链接器等)做一些更聪明的事情。

一些特定的实现做得更聪明一些,因此即使在编译器不可见的情况下也可以实际内联函数。例如,在一个基本的“编译所有源文件然后链接”工具链中,智能链接器可能意识到一个函数很小并且只调用了几次,并选择(实际上)内联它,即使内联的点发生对编译器不可见(例如,因为调用函数的语句在单独的编译单元中,函数本身在另一个编译单元中)所以编译器不会进行内联。

事实是,标准并没有阻止实现这样做。它只是陈述了所有实现行为的最低要求集。

从本质上讲,编译器对要内联的函数具有可见性的要求是标准的最低要求。如果以这种方式编写程序(例如,所有要内联的函数都在其头文件中定义),则标准保证它将适用于每个(符合标准的)实现。

但这对我们更智能的工具链意味着什么?更智能的工具链必须从格式良好的程序中产生正确的结果——包括在使用这些函数的每个编译单元中定义内联函数的程序。我们的工具链被允许做更聪明的事情(例如在编译单元之间窥视)但是,如果代码是以需要这种更智能的行为的方式编写的(例如编译器在编译单元之间窥视)代码可能会被另一个工具链拒绝。

最后,每个 C++ 实现(工具链、标准库等)都需要符合 C++ 标准的要求。反之则不然——一个实现可能比标准要求的更聪明,但这并不要求其他实现以兼容的方式做事。

从技术上讲,内联不限于编译器的功能。它可能发生在编译器或链接器中。它也可能发生在运行时——例如,“Just In Time”技术实际上可以在运行几次后重组可执行代码,以提高后续性能[这通常发生在虚拟机环境中,这允许这些技术的好处,同时避免与自修改可执行文件相关的问题]。

关于c++ - 如果编译器可以自行内联函数,为什么内联函数必须在 header 中为 "defined",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37163466/

相关文章:

c++ - 捕获无效的操作码 rip rsp

c++ - MFC中如何将GUI与逻辑分离?

javascript - 如何使用 JavaScript 中的函数翻译输入

我们可以在 C 的不同函数中声明相同的局部静态变量吗?

c - 基于函数的 CPE,如何计算下限?

optimization - 在 OpenCL 中构建偏移邻域操作的更快方法

c++ - 与条件 noexcept 和重载不一致

c++ - OpenGL 局部绘图

function - 在PowerShell中的foreach函数中更改变量名称

c# - MS C# 编译器和非优化代码