内联函数和静态内联函数的区别

32

有人能告诉我内联函数和静态内联函数的区别吗?

在哪些情况下应该优先使用静态内联而不是内联?

我问这个问题是因为我有一个内联函数,在链接时遇到编译问题(重定位错误:...符号已经被舍弃与已舍弃的部分...)。我将其更改为普通函数,它可以正常工作。现在我的一些前辈告诉我尝试使用静态内联。以下是我的函数:

inline void wizSendNotifier (const char* nn_name, bpDU* arg=0, int aspect = -1)
{
   wizuiNotifier* notifier = ::wizNtrKit.getNotifier (nn_name);
   notifier->notify (arg, aspect);
}

而这不是在类内部。这是在头文件中!

我猜调用静态函数只应该在定义它的特定TU中进行。

由于我的函数在头文件中,如果我将其设置为静态的,那么无论我在哪里包含该头文件,静态函数都可以在该翻译单元中使用吗?


这个函数是在类里面吗?请同时发布它的声明。 - anatolyg
2
::wizNtrKit 是一个静态对象吗?它的链接是什么? - Walter
此外,这个函数出现在哪里?头文件,源文件?有多少个源文件包含它? - Steve Jessop
该函数出现在一个名为steve的头文件中。大约有50个源文件包含了这个头文件。 - Vijay
1个回答

48

非静态 inline 函数声明在每个使用它的翻译单元(源文件)中都指向同一个函数。

一致性规则要求每个包含函数定义的翻译单元必须完全相同,定义 “相同”的方式比较严格。通常情况下,只要源文件都使用相同的头文件并且函数不使用任何具有内部链接的全局名称(包括静态函数)或任何在不同的翻译单元中定义的宏,就可以满足此要求。

我不记得以前遇到过这种特定的链接器错误,但可能是其中之一的限制造成的。如果不满足要求,则会出现未定义行为而不需要进行诊断,您有责任满足这些要求。

静态内联static inline函数声明在每个翻译单元中都指向不同的函数,只是它们恰好具有相同的名称。它可以使用具有不同定义的静态全局名称或宏,因此在不同的翻译单元中,该函数可能会表现出不同的行为,即使在头文件中看起来相同也是如此。

由于这种差异,如果函数包含任何静态局部变量,则根据其是否为static而表现出不同的行为。如果它是 static,则每个翻译单元都有自己的版本和局部变量的副本。如果只是内联,则所有翻译单元都使用相同的静态局部变量副本。


6
注意:对于static函数,inline关键字失去了其语义意义(如果该函数定义出现在多个TUs中,则没有问题);唯一与inline相关的是向编译器发送的一个简单提示,大多数情况下忽略它。 - Matthieu M.
1
是的,我所说的关于inline函数的内容也适用于既不是static又不是inline的函数声明,除了“单一定义规则”要求。它不需要在每个TU中都有相同的定义,而只需要一个TU包含所有的定义。鉴于提问者的代码在去掉inline后可以正常工作,我怀疑这里有什么奇怪的情况——如果在多个TU中定义它,你应该期望进行链接器错误检查。我不认为需要诊断,但对于链接器来说,这并不是一个困难的问题。 - Steve Jessop

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接