现代c++编译器能否内联在cpp文件中定义的函数
Can modern C++ compilers inline functions that are defined in a cpp file
我知道关键字inline
具有有用的属性,例如在头文件中保持模板专门化。另一方面,我经常读到,inline
几乎是无用的提示,为编译器实际上内联函数。此外,该关键字不能在cpp文件中使用,因为编译器希望在调用标记有inline
关键字的函数时检查它们。
因此,我对现代编译器(即gcc 4.43)的"自动"内联功能有点困惑。当我在cpp中定义一个函数时,如果编译器认为内联对函数有意义,那么它是否可以内联它,或者我是否剥夺了他的一些优化能力?(这对于大多数函数来说是可以的,但对于经常调用的小函数来说,重要的是要知道)
在编译单元内,编译器不会有内联函数的问题(即使它们没有被标记为内联)。跨编译单元更难,但现代编译器可以做到。
使用inline tag
对'现代'编译器以及它是否实际上内联函数(它具有比人类思维更好的启发式)几乎没有影响(除非您指定标志以某种方式强制它(这通常是一个坏主意,因为人类不擅长做出这个决定))。
至少从Visual Studio 2005开始,Microsoft Visual c++就能够做到这一点。他们称之为"整个程序优化"或"链接时间代码生成"。在此实现中,编译器实际上不会生成机器码,而是将预处理的c++代码写入目标文件中。然后链接器将所有的代码合并到一个巨大的代码单元中,并执行实际的编译。
GCC至少从4.5版开始就能做到这一点,在GCC 4.7中将有重大改进。据我所知,这个特性仍然被认为是实验性的(至少到目前为止,许多Linux发行版还没有使用它)。GCC的实现方式非常相似,首先将预处理的源代码(用其GIMPLE中间语言)写入目标文件,然后将所有目标文件编译成单个目标文件,然后将其传递给链接器(这允许GCC继续使用现有的链接器)。
许多大型c++项目也做现在被称为"统一构建"的事情。不需要将数百个单独的c++源文件传递到编译器中,而是创建一个源文件,其中包含项目中所有其他源文件。这样做的初衷是为了减少编译时间(因为头文件等不需要一遍又一遍地解析),但作为副作用,它会产生与上面提到的LTO/LTCG技术相同的结果:让编译器完美地看到所有编译单元中的所有函数。
我对我的c++编译器(MSVC 2010)的独创性和它的愚蠢印象深刻。一些通过模板进行像素格式转换的代码,在适当内联时可以分解为5-10个汇编指令,但却膨胀成数千字节(!)的嵌套函数调用。在其他时候,它如此积极地内联,以至于整个类消失,即使它们包含重要的功能。
这取决于您的编译标志。对于-combine
和-fwhole-program
, gcc
将跨cpp边界进行函数内联。如果你编译成多个目标文件,我不确定链接器会做多少。
标准没有规定函数如何内联。如果编译器可以访问函数的实现,它们可以内联函数。如果你只有一个二进制文件的头文件,这是不可能的。如果它在同一个模块中,编译器可以内联函数,即使它在cpp
文件中。
- .cpp和.h文件中的模板专用化声明
- 为什么两个不同的未命名名称空间可以共存于一个cpp文件中
- 命名空间中具有.h和.cpp文件的类
- 为什么我的主文件.cpp不打印头文件中的任何内容
- 生成文件错误 - 找不到文件 - *.cpp
- 如何在文件.cpp gtkmm中声明小部件
- 没有实现文件(.cpp)的派生类
- 如何使用"CMakeLists.txt"中的add_library将整个文件(.cpp,.h等)包含在目录中
- 如何在Linux / Windows操作系统上使用文件*.cpp一步编译下面的代码
- 关于 Linux .so 文件无法链接到主文件.cpp文件
- 文件.cpp从Windows到Linux
- Ubuntu C++ 编译器错误: g++: 错误: 文件.cpp: 没有这样的文件或目录
- 如何将文件.cpp编译为本机编译
- 使用模板类时,似乎无法包含除 main 以外的任何 cpp 文件.cpp
- 无法编译C++文件.cpp。C++98模式
- 为什么C++头文件不需要包含实现文件 (.cpp)
- 如何访问位于独立文件(.cpp)中的非成员函数
- 如何在Visual Studio Code中通过键盘快捷键切换头文件/cpp文件
- 如何将数据从stringstream写入文件(CPP)
- 为什么filestream不把空白写入文件cpp ?