我在阅读其他代码时遇到了一个有趣的案例。
在头文件中,定义的静态变量和内联函数简化如下:
static int ply;
inline int WTM(){return ply;}
并在包含此头部的其他cpp
文件中调用该函数。
cout << ply << " " << WTM();
奇怪的是,在调用此函数的地方,内联函数中的变量ply
与函数外部之前的相同变量具有不同的值。
输出为0 1;
我检查了所有文件,ply
和WTM()
只有这个单一的定义。
之后我将代码更改为以下内容:
static int ply;
static inline int WTM(){return ply;}
两个值变得相同。
我的编译器为g++ (GCC) 4.4.7
,默认设置为。
我搜索了这个现象并得到了这两个链接:
Difference between an inline function and static inline function
和
http://gcc.gnu.org/onlinedocs/gcc/Inline.html
但仍然不明白为什么会发生这种情况(特别是为什么他们在第一种情况下会有不同的价值观)。我想知道是否有人可以告诉我编译器将如何扩展这两段代码(我尝试使用-E
但它似乎不能用于内联函数)。
答案 0 :(得分:5)
这是因为静态变量将在包含头文件的所有翻译单元中单独定义,但(非静态)函数将仅定义一次。因此,您拥有变量的多个副本,但只有一个函数副本。该函数使用哪个变量副本?我不知道,我认为它是未定义的行为或实现定义(必须阅读规范)。
当您将函数声明为static
时,有什么不同,那就是它将在每个转换单元中定义与变量相同,因此只访问该转换单元的变量。
答案 1 :(得分:0)
首次使用没有静态的内联函数是未定义的行为。
标准3.2.6,
可以有多个......,...,内联函数的定义 与外部联系(7.1.2),...,在一个程序中提供每个 定义出现在不同的翻译单元中,并提供了 定义满足以下要求:
- D的每个定义应由相同的令牌序列组成;和
- 在D的每个定义中,查找相应的名称 根据3.4,应指在其中定义的实体 D的定义,或者指同一实体,
- ...
如果D的定义满足所有这些要求,那么 程序应该表现得好像有一个单一的定义D.如果 D的定义不满足这些要求,那么行为 未定义。
首次使用外部内联函数(无静态)时,名称查找后的ply名称引用不同翻译单元的实体。
答案 2 :(得分:0)
还有一个解释:
通过声明函数inline
,
您可以指示编译器将该函数的代码集成到其调用者的代码中。
通过消除函数调用开销,可以更快地执行; 此外,如果任何实际参数值是常量,则它们的已知值可能允许在编译时进行简化,因此不需要包括所有内联函数的代码。
对代码大小的影响不太可预测;函数inline
的对象代码可能更大或更小,具体取决于具体情况。
Inline
函数是一种优化,它只在优化编译时才“有效”。如果你不使用-O,那么真正的函数不是inline
。
和static inline function
:
当某个功能同时为inline
和static
时,
如果对函数的所有调用都集成到调用者中,并且从不使用函数的地址,则永远不会引用函数自己的汇编代码。
在这种情况下,compiler
实际上不会输出函数的汇编代码,除非您指定选项-fkeep-inline-functions.
由于各种原因无法集成某些调用(特别是,无法集成函数定义之前的调用,也无法在定义中进行递归调用)。
如果存在非集成调用,则该函数将照常编译为汇编代码。如果程序引用其地址,则必须像往常一样编译该函数,因为它不能是inlined
。
答案 3 :(得分:-1)
使用参考What's the difference between “static” and “static inline” function?:
inline
指示编译器尝试将函数内容嵌入到调用代码中,而不是执行实际调用。
对于频繁调用的小功能,可以产生很大的性能差异。
然而,这只是一个“提示”,并且编译器可能会忽略它,并且大多数编译器将尝试“inline
”即使不使用关键字,作为优化的一部分,它可能
例如:
static int Inc(int i) {return i+1};
.... // some code
int i;
.... // some more code
for (i=0; i<999999; i = Inc(i)) {/*do something here*/};
这个紧密循环将在每次迭代时执行函数调用,并且函数内容实际上远小于编译器执行调用所需的代码。 inline将基本上指示编译器将上面的代码转换为等效的:
int i;
....
for (i=0; i<999999; i = i+1) { /* do something here */};
跳过实际的函数调用并返回
显然,这是一个展示要点的例子,而不是真正的代码。
static
指的是范围。在C中,它表示函数/变量只能在同一个翻译单元中使用。