内联成员函数使用的静态全局变量

时间:2011-03-07 10:47:48

标签: c++ gcc global-variables

如果C ++头文件中有静态全局变量,则包含头文件的每个翻译单元都会以自己的变量副本结束。

但是,如果我在同一个头文件中声明一个类,并创建该类的成员函数,在类声明中实现内联,它使用静态全局变量,例如:

#include <iostream>

static int n = 10;

class Foo {
 public:
   void print() { std::cout << n << std::endl; }
};

然后我在gcc 4.4下看到了一些奇怪的行为:

  1. 如果我在没有优化的情况下编译,则所有成员函数的使用都使用其中一个翻译单元(g ++命令行中提到的第一个)的变量副本。

  2. 如果我使用-O2进行编译,则每次使用成员函数都会使用来自翻译单元的变量副本。

  3. 显然这是一个非常糟糕的设计,所以这个问题只是出于好奇。但是,我的问题是,C ++标准对此案例的说法是什么?通过在启用和不启用优化的情况下提供不同的行为,g ++是否正常运行?

1 个答案:

答案 0 :(得分:12)

标准说(3.2 / 5):

  

可以有多个定义   类的类型(第9条),   ......如果定义满足   以下要求......各自   D的定义,相应的名称,   按照3.4,向上看   指在该中定义的实体   D的定义,或者指的是   同一实体

这是您的代码丢失的地方。 nFoo的不同定义中的使用不是指同一个对象。游戏结束,未定义的行为,所以是的,gcc有权在不同的优化级别做不同的事情。

3.2 / 5继续:

  

除了名称可以引用a   const对象有内部或没有   如果对象具有相同的链接   所有的积分或枚举类型   D的定义,对象是   用常量表达式初始化   (5.19),和值(但不是   使用对象的地址)   该对象具有相同的值   D的定义

因此,在您的示例代码中,您可以将n变为static const int并且一切都很可爱。这个子句描述了不同的TU是否“引用”相同的对象或不同的对象 - 它们使用的是编译时常量值并且它们都使用相同的对象的条件,这并不是巧合。 / p>