【问题标题】:Static global variable used by inline member function内联成员函数使用的静态全局变量
【发布时间】:2011-03-07 10:47:48
【问题描述】:

当您在 C++ 头文件中有一个静态全局变量时,包含该头文件的每个翻译单元都会以自己的变量副本结束。

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

#include <iostream>

static int n = 10;

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

然后我看到 gcc 4.4 下的行为有点奇怪:

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

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

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

【问题讨论】:

标签: c++ gcc global-variables


【解决方案1】:

标准说 (3.2/5):

可以有多个定义 类类型(第 9 条), ...只要定义满足 以下要求......在每个 D的定义,对应的名称, 按 3.4 查,应 指的是定义在 D的定义,或应参考 同一实体

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

3.2/5 继续:

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

因此,在您的示例代码中,您可以将n 变成static const int,一切都会很可爱。这不是巧合,该条款描述了不同的 TU “引用”相同对象或不同对象没有区别的条件 - 它们使用的只是编译时常量值,并且它们都使用相同的值。

【讨论】:

  • 优秀的答案。谢谢。
猜你喜欢
  • 1970-01-01
  • 2016-07-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-08
  • 1970-01-01
  • 2011-06-11
相关资源
最近更新 更多