内联的目的是什么?

Def*_*ult 15 c++ compiler-construction inline

我与Johannes Schaub就关键字进行了讨论.那里的代码是这样的:inline

namespace ... {
    static void someFunction() {
        MYCLASS::GetInstance()->someFunction();
    }
};
Run Code Online (Sandbox Code Playgroud)

他说:

将其作为内联函数可以在可执行文件中保存代码大小

但根据我在这里这里的发现,不需要,因为:

  • [内联]仅在编译器的成本/收益分析显示为有利可图时才会出现
  • 主流C++编译器(如Microsoft Visual C++和GCC)支持一个选项,允许编译器自动内联任何合适的函数,甚至那些未标记为内联函数的函数.

然而,约翰内斯表示明确指定它还有其他好处.不幸的是我不理解他们.例如,他说,"内联"允许您在程序中多次定义函数.,我很难理解(并找到参考).

所以

  1. 是否inline只是编译器的建议?
  2. 当你有一个小功能时我是否应该明确说明(我猜1-4指令?)
  3. 写作有什么其他好处inline
  4. 是否需要声明inline以减少可执行文件的大小,即使编译器(根据维基百科[我知道,错误的引用])应该自己找到这样的函数?

还有什么我想念的吗?

Joh*_*itb 6

重申我在那些小评论框中所说的话.特别是,我从来没有谈论inlin- ING:

// foo.h:
static void f() {
  // code that can't be inlined
}

// TU1 calls f
// TU2 calls f
Run Code Online (Sandbox Code Playgroud)

现在,TU1和TU2都有自己的副本f- f可执行文件中的代码两次.

// foo.h:
inline void f() {
  // code that can't be inlined
}

// TU1 calls f
// TU2 calls f
Run Code Online (Sandbox Code Playgroud)

两个TU都将发出特殊标记的版本,f这些版本由链接器有效地合并,丢弃除了其中一个之外的所有版本.代码f只在可执行文件中存在一次.

因此,我们在可执行文件中节省了空间.


dir*_*tly 3

\n

内联只是对编译器的建议吗?

\n
\n\n

是的。

\n\n
\n

7.1.2 函数说明符

\n\n

2带有内联说明符的函数声明(8.3.5、9.3、11.4)声明内联函数。inline\n 说明符向实现表明,在调用点\n 处函数体的内联替换优先于通常的函数调用机制。不需要实现在调用时执行此内联替换;然而,即使省略此内联替换,仍应遵守 7.1.2 定义的内联函数的其他规则。

\n
\n\n

例如来自 MSDN:

\n\n
\n

编译器将内联扩展选项和关键字视为建议。不保证函数会被内联。即使使用 __forceinline 关键字,也不能强制编译器内联特定函数。使用 /clr 进行编译时,如果函数应用了安全属性,编译器将不会内联该函数。

\n
\n\n

但请注意:

\n\n
\n

3.2 单一定义规则

\n\n

3 [...]内联函数应在使用该函数的每个翻译单元中定义。

\n\n

4内联函数应在使用它的每个翻译单元中定义,并且在每种情况下都应具有完全相同的定义(3.2)。[ 注意:在其定义出现在翻译单元中之前,可能会遇到对内联函数的调用。\xe2\x80\x94end note ] 如果函数的定义出现在其第一个内联声明之前的翻译单元中,则程序格式错误。如果具有外部链接的函数在一个翻译单元中被声明为内联,则应在其出现的所有翻译单元中将其声明为内联;不需要任何诊断。具有外部链接的内联函数在所有翻译单元中应具有相同的地址。extern 内联函数中的静态局部变量始终引用同一个对象。\n extern 内联函数主体中的字符串文字是不同翻译单元中的同一对象。\n [ 注意:出现在默认值中的字符串文字参数表达式不在内联函数的主体中,仅仅是因为该表达式用于该内联函数的函数调用中。\xe2\x80\x94end note ] 在外部内联函数体内定义的类型在每个翻译单元中都是相同的类型。

\n
\n\n

[注:强调我的]

\n\n

TU 基本上是一组标头加上一个实现文件 ( .cpp),该实现文件生成一个目标文件。

\n\n
\n

当你有一个小函数时是否应该明确说明(我猜有 1-4 条指令?)

\n
\n\n

绝对地。为什么不帮助编译器帮助您生成更少的代码呢?通常,如果序言/结尾部分比内联强制编译器生成它们会产生更多成本?但在开始内联之前,您必须、绝对必须阅读这篇 GOTW 文章: GotW #33:内联

\n\n
\n

内联编写还有什么其他好处?

\n
\n\n
    \n
  • namespace也可以inline。请注意,类体本身中定义的成员函数默认是内联的。隐式生成的特殊成员函数也是如此。

  • \n
  • 函数模板不能在实现文件中定义(请参阅FAQ 35.12),除非您提供显式实例化(对于使用模板的所有类型 - 通常是 PITA IMO)。请参阅有关将模板移出头文件的 DDJ 文章(如果您感觉奇怪,请阅读另一篇关于export从标准中删除的关键字的文章。)

  • \n
\n\n
\n

是否需要声明内联以减少可执行文件的大小,即使编译器(根据维基百科[我知道,不好的参考])本身应该找到这样的函数?

\n
\n\n

再次,正如我所说,作为一名优秀的程序员,您应该在可能的情况下帮助编译器。但这C++ FAQ 必须提供的有关inline. 所以要小心。并非所有编译器都会进行此类分析,因此您应该阅读有关其优化开关的文档。例如:GCC 做了类似的事情:

\n\n
\n

您还可以指示 GCC 尝试使用选项 -finline-functions 将所有 \xe2\x80\x9csimple enough\xe2\x80\x9d 函数集成到其调用者中。

\n
\n\n

大多数编译器允许您在某种程度上覆盖编译器的成本/效益比分析。MSDN和GCC文档值得一读

\n