头文件中实现的函数的静态与内联 我认为C++中的代码>内联< /COD>是用于链接/范围的。对于全局对象,我将其与extern和static放在同一个篮子中

头文件中实现的函数的静态与内联 我认为C++中的代码>内联< /COD>是用于链接/范围的。对于全局对象,我将其与extern和static放在同一个篮子中,c++,C++,通常,对于在头文件中实现的函数,我的解决方案是将其设置为静态: // In Foo.h static void foo() { // Do stuff... } 但是,我认为这也是有效的,并且似乎没有违反ODR: // In Foo.h inline void foo() { // Do stuff... } 这两者在语义上有什么区别?另外,我不太清楚C++标准的哪些方面能解释精确的差异,或者它只是未定义的,并且与执行不同。 在很多情况下,你不会注意到不同,因为编译器和链接器

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

// In Foo.h
static void foo()
{
    // Do stuff...
}
但是,我认为这也是有效的,并且似乎没有违反ODR:

// In Foo.h
inline void foo()
{
    // Do stuff...
}

这两者在语义上有什么区别?另外,我不太清楚C++标准的哪些方面能解释精确的差异,或者它只是未定义的,并且与执行不同。

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

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

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

inline
准确地传达了您想要的内容:“请抑制此函数的ODR(一个定义规则),以便每个翻译单元可以(并且必须)执行此操作。”提供其自己的函数定义副本”

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

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


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

主要区别在于函数中任何静态局部变量的情况——如果函数是
静态的
,则每个编译单元都有其自己的静态局部变量副本,不同于任何其他编译单元。如果函数是
内联的
,则只有一(组)静态局部变量所有编译单元都有共享。

< P>没有人提到C++中的静态函数是直接调用的,不是在类的实例上调用的。换句话说,没有隐含的“this”指针。如果类MyClass的函数FO是静态的,则称:

MyClass::foo();//调用它

而不是: MyClass an_对象=新建MyClass();
一个对象->foo()

请看这篇关于内联、静态和静态内联函数的文章。当您在头文件中定义具有内部链接的函数时,很容易出现ODR冲突。@我确实查看了它,但我觉得它没有多大帮助,特别是考虑到我不是特别关心如何将
静态内联
一起使用。Ju这两种语言的语义差异适用于我设计的示例。不幸的是,这两种语言的答案并不能满足我的未知条件。如果你使用
静态内联
,那么呢?@jrok:
静态内联
在语义上与
静态
相同——唯一的区别是编译器提示可能没有效果@chrisdd是的,这也许值得一提?你能澄清一下“每个翻译单元都可以(而且必须)提供自己的副本”和“这样生成的函数在可执行文件中只存在一次”吗?这似乎是矛盾的。@s.bandara编译器要求包含函数调用的每个TU也包含函数的定义。换句话说,该函数必须存在于每个TU中(或至少存在于使用该函数的每个TU中)。但是链接器需要将函数的所有这些实例合并在一起,因此最终可执行文件将只有一个函数实例(最多。如果所有调用都是内联的,则可能没有),因为这是完全不相关的。对于成员函数,static关键字使其成为静态成员函数(如您所述).但对于非成员函数,如问题中所述,static关键字提供函数静态链接(它在当前翻译单元外不可见)。