C++ 访问静态变量时内联函数和静态内联函数之间的差异
在阅读其他代码时,我遇到了一个有趣的案例 在头文件中,定义的静态变量和内联函数简化如下:C++ 访问静态变量时内联函数和静态内联函数之间的差异,c++,gcc,static,inline,C++,Gcc,Static,Inline,在阅读其他代码时,我遇到了一个有趣的案例 在头文件中,定义的静态变量和内联函数简化如下: static int ply; inline int WTM(){return ply;} 该函数在包含该头的其他cpp文件中调用 cout << ply << " " << WTM(); 这两个值变得相同 我的编译器是带有默认设置的g++(GCC)4.4.7 我搜索了这个现象,找到了两个链接: 和 但仍然不明白为什么会发生这种情况(特别是为什么他们在第一种情况下会
static int ply;
inline int WTM(){return ply;}
该函数在包含该头的其他cpp
文件中调用
cout << ply << " " << WTM();
这两个值变得相同
我的编译器是带有默认设置的g++(GCC)4.4.7
我搜索了这个现象,找到了两个链接:
和
但仍然不明白为什么会发生这种情况(特别是为什么他们在第一种情况下会有不同的价值观)。我想知道是否有人能告诉我编译器将如何扩展这两段代码(我尝试使用
-E
,但它似乎不适用于内联函数)。这是因为静态变量将在包含头文件的所有翻译单元中单独定义,但(非静态)变量函数将只定义一次。因此,变量有多个副本,但函数只有一个副本。函数将使用变量的哪个副本?我不知道,我认为要么是未定义的行为,要么是定义了实现(必须阅读规范)
当您将函数声明为
静态
时,不同之处在于,它将在每个转换单元中定义为与变量相同,因此,只访问该翻译单元的变量。这是因为静态变量将在包含头文件的所有翻译单元中单独定义,但(非静态)函数将只定义一次。因此,变量有多个副本,但函数只有一个副本。函数将使用变量的哪个副本?我不知道,我认为要么是未定义的行为,要么是定义了实现(必须阅读规范)
将函数声明为静态函数时的不同之处在于,它将在每个转换单元中定义为与变量相同的变量,因此仅访问该转换单元的变量。使用引用:
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*/};
static int Inc(int i){return i+1};
.... // 一些代码
int i;
.... // 还有代码吗
对于(i=0;i使用参考:
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*/};
static int Inc(int i){return i+1};
..//一些代码
int i;
..//还有一些代码吗
对于(i=0;i您第一次使用不带static的内联函数是未定义的行为
标准3.2.6
内联函数可以有多个定义
程序中的外部链接(7.1.2),…,前提是
定义显示在不同的翻译单元中,并提供
定义满足以下要求:
-D的每个定义应包含相同的令牌序列;以及
-在D的每个定义中,查找对应的名称
根据第3.4条,应指本协议中定义的实体
D的定义,或应指同一实体
-
如果D的定义满足所有这些要求,则
程序的行为应与D的定义相同。如果
D的定义不满足这些要求,那么行为
没有定义
对于您第一次使用外部内联函数(无静态),在名称查找后,ply的名称指不同翻译单元的不同实体。您第一次使用无静态的内联函数是未定义的行为
标准3.2.6
内联函数可以有多个定义
程序中的外部链接(7.1.2),…,前提是
定义显示在不同的翻译单元中,并提供
定义满足以下要求:
-D的每个定义应包含相同的令牌序列;以及
-在D的每个定义中,查找对应的名称
根据第3.4条,应指本协议中定义的实体
D的定义,或应指同一实体
-
如果D的定义满足所有这些要求,则
程序的行为应与D的定义相同。如果
D的定义不满足这些要求,那么行为
没有定义
对于您第一次使用外部内联函数(无静态),在名称查找后,ply的名称指的是不同翻译单位的不同实体。对此还有一个解释:
通过声明函数内联
,
您可以指示编译器将该函数的代码集成到其调用方的代码中
这通过消除函数调用开销使执行更快;
此外,如果任何实际参数值是常量,那么它们的已知值可能允许在编译时进行简化,因此不需要包含所有内联函数的代码
影响
int i;
....
for (i=0; i<999999; i = i+1) { /* do something here */};