静态vs内联函数在头文件中实现

voi*_*ter 15 c++

inline在C++中的想法是用于链接/作用域.我把它externstatic全局对象放在同一个篮子里.

通常,对于在头文件中实现的函数,我的首选解决方案是将其设置为静态:

// In Foo.h
static void foo()
{
    // Do stuff...
}
Run Code Online (Sandbox Code Playgroud)

但是,我相信这也是有效的,似乎并没有违反ODR:

// In Foo.h
inline void foo()
{
    // Do stuff...
}
Run Code Online (Sandbox Code Playgroud)

两者之间有什么语义差异?另外,我不确定C++标准的哪些区域可以解释确切的差异,或者它是否仅仅是未定义的,并且差异在于实现.

jal*_*alf 19

inline 准确地传达你想要的东西:"请为这个功能压制ODR(一个定义规则),这样每个翻译单元都可以(并且必须)提供它自己的函数定义副本".

然后,编译器将内联对函数的调用,或者将来自不同TU的函数定义合并在一起(以便生成的函数在可执行文件中存在一次).

static另一方面,告诉编译器在定义它的每个转换单元中生成函数,而不是共享它.因此,您最终会在生成的可执行文件中存在任意数量的技术上独立的函数.

简而言之,如果你使用static,那么在不同的翻译单元中获取函数的地址将返回不同的地址(因为你告诉编译器在每个TU中生成一个函数),但如果你使用inline,它们将显示相同的地址(因为你定义了一个函数,只是告诉编译器将许多定义合并在一起).

  • @ChrisDodd 是的,也许值得一提? (3认同)
  • 如果你做`静态内联'怎么办呢? (2认同)
  • @jrok:“static inline”在语义上与“static”相同——唯一的区别是编译器提示可能没有效果。 (2认同)
  • 您能否澄清“每个翻译单元可以(并且必须)提供其自己的副本”和“以使生成的功能在可执行文件中仅存在一次”?看来是矛盾的。 (2认同)
  • @s.bandara 编译器要求每个包含函数调用的 TU 也包含它的定义。换句话说,该函数必须存在于每个 TU 中(或者至少存在于每个使用该函数的 TU 中)。但是链接器需要将函数的所有这些实例合并在一起,因此最终的可执行文件将只有一个函数实例(最多。如果*所有*调用都是内联的,则它可能有零个实例) (2认同)

Chr*_*odd 6

主要区别在于函数中的任何静态局部变量 - 如果函数是,static则每个编译单元将具有与任何其他编译单元不同的静态局部变量.如果函数是inline,则所有编译单元只共享一个(一组)静态本地.


joe*_*ing 5

在许多情况下,您不会注意到差异,因为现在编译器和链接器非常聪明。但是,内联函数的行为必须与常规函数一样。头文件中的静态函数将被编译到包含它的每个源文件中 - 因此会有很多它的副本。

大多数情况下,这并不重要,但有几种方法可以做到。内联函数有一个地址。静态函数在每个翻译单元中会有不同的地址。

静态局部变量:对于内联,它们将有一个副本。对于静态函数,对于包含该函数的每个翻译单元,每个静态局部变量都会有一个唯一的副本。