c++内联函数和重声明



首先为我的英语感到抱歉。

由于GCC完全忽略了内联说明符,所以我很难知道一个函数是否被我标记为内联。我想理解的是,当你有一个相同的函数的一些重新声明(在相同的翻译单元或在不同的),何时或在哪种情况下你的函数被标记为内联或不(不管编译器会用你的提示做什么)。

例如:

inline void print();
void print();

或:

void print();
inline print();

用不同的内联说明符重新声明一个函数的意义是什么?一个更复杂的例子:

#include <iostream>
void print();
int main()
{
    print(); // (1)
}
inline void print() { std::cout << "HELLO" << std::endl; }

从c++独有的角度来看,而不是从编译器的角度来看,print函数在(1)行是内联函数吗?

我不能简明地表述我的问题,但我认为消息已经收到:)我试图理解一个函数应该被标记为内联的时候,而不是从c++和程序员的角度来看(不管编译器会用你的函数做什么)。

这句话

由于GCC完全忽略内联说明符,这有点困难对于我来说,知道一个函数是否被我标记为内联

是一个不正确的起始基。(当然,在本讨论中,我们可以用任何其他现代编译器替换GCC)。

当然,编译器可能会忽略inline关键字来决定函数是否内联,并且它当然可以内联未标记为内联的函数。但是,在生成最终输出时,编译器确实使用inline关键字[它相当于"在结构体内部声明的体"],以避免在不同的编译单元中多次生成代码的函数的多个定义。例如:

 foo.h:
    inline int foo() { return 42; }
 a.cpp:
    #include "foo.h"
    ...
 b.cpp:
    #include "foo.h"
    ... 

如果函数foo没有声明为inline,如果我们将a.p p和b.p p的结果链接到一个可执行文件中,链接器会抱怨函数foo的多个定义。

然而,你是对的,编译器不会根据inline关键字来决定内联函数,而是根据其他方面来决定,比如函数被调用了多少次,函数的源代码对编译器是否"可见",等等。

作为一个简单的规则:

  1. 编译器将内联函数,它没有源代码。
  2. 编译器将内联虚函数(除非它能确定虚函数所属对象的类型)
  3. 编译器内联小函数和/或只调用一次的函数,特别是如果函数是静态的。

由于内联发生在编译结束时(当所有源代码都被解析并放置在某种AST(抽象语法树)或类似形式中时),函数是在使用点之前还是之后通常并不重要-当然,如果调用的函数不是AST的一部分(源代码不可用),编译器别无选择,只能不内联它。

"当源不可用时不能内联"的例外是所谓的LTO"链接时间优化"。传统的链接器只会收集一组机器代码指令,并按照它们列出的顺序将它们粘贴在一起,而不需要了解函数是什么[简化的视图,足以用于此讨论],然后为编译器无法直接解析的函数和变量修复任何地址。相比之下,LTO将"目标文件"存储为中间表示,最后的机器码生成由链接器阶段完成。这意味着链接器有足够的信息来移动代码,例如将一个函数中的代码内联到另一个函数中。该技术可以在最近的版本中使用,例如gcc(4.9.0将LTO作为一个完整的特性,早期版本的支持略少)

inline允许在两个或多个翻译单元中定义外部链接函数(本质上相同)。

这意味着在头文件中定义它。

当一个函数是inline时,它必须被定义,而inline,本质上是1)在每个使用它的翻译单元中都是相同的。


inline只是累积。函数不能变成un- inline .


除了这些考虑之外,inline还可以作为一个优化提示,编译器可以自由地忽略它。在这种情况下,它声明您希望内联对该函数的机器代码调用。一般来说,编译器可以更好地判断这在哪里是好主意或不好。

1 c++ 17 10.1.6/5 (dcl.inline/5): "内联函数或变量应在每个使用它的翻译单元中定义,并且在任何情况下都应具有完全相同的定义"

相关内容

  • 没有找到相关文章

最新更新