如何在头文件中添加函数定义?
这可以通过 3 种可能的方式实现:
- 标记功能
inline
或
- 制作函数
static
或
- 将函数放在匿名命名空间中。
这样做的正确方法是什么?
#1
即:标记函数inline
是正确的方法,而不会破坏One Definition Rule。
其他两种方法有什么问题?
在这两个#2
和#3
每个翻译单元中都将包含它自己的函数版本,并且程序将包含函数的几个不同版本,从而导致生成的二进制文件的大小增加。
即:对于一个static
函数fun()
,&fun
在每个翻译单元中会有所不同,程序会包含N
不同版本的函数。
此外,如果函数包含静态局部变量,那么将有N
不同的静态局部变量,每个函数实例一个。
第一种方法如何避免这个问题?
inline
函数具有外部链接。
当您标记一个函数时inline
,该函数将在所有翻译单元中具有相同的地址。此外,在内联函数体内定义的静态局部变量和字符串文字在翻译单元中被视为相同的对象。
简而言之,内联函数将在所有翻译单元中具有相同的地址。
头文件中的static inline
函数定义是怎么回事?
static
关键字强制函数具有内部链接。
每个定义为 inline 的函数实例都被视为一个单独的函数,并且每个实例都有自己的静态局部变量和字符串文字的副本。因此,这将类似于#2
。
注意:
该标准要求inline
用户程序中的所有函数定义必须在使用或调用该函数的所有翻译单元中具有完全相同的定义。
相关标准参考:
C++03 标准
3.2 一个定义规则:
第 3 段:
每个程序都应包含该程序中使用的每个非内联函数或对象的一个定义;无需诊断。定义可以显式出现在程序中,可以在标准或用户定义库中找到,或者(在适当时)隐式定义(参见 12.1、12.4 和 12.8)。内联函数应在使用它的每个翻译单元中定义。
7.1.2 函数说明符
第 4 段:
内联函数应在使用它的每个翻译单元中定义,并且在每种情况下都应具有完全相同的定义(3.2)。[注意:在其定义出现在翻译单元之前,可能会遇到对内联函数的调用。] 如果具有外部链接的函数在一个翻译单元中声明为内联,则应在其出现的所有翻译单元中声明为内联;不需要诊断。具有外部链接的内联函数在所有翻译单元中应具有相同的地址。anextern 内联函数中的静态局部变量始终引用同一个对象。外部内联函数中的字符串文字是不同翻译单元中的相同对象。