简体   繁体   English

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

[英]Static global variable used by inline member function

When you have a static global variable in a C++ header file, each translation unit that includes the header file ends up with its own copy of the variable. 当您在C ++头文件中有一个静态全局变量时,包含头文件的每个翻译单元最终都会有自己的变量副本。

However, if I declare a class in that same header file, and create a member function of that class, implemented inline within the class declaration, that uses the static global variable, for example: 但是,如果我在同一个头文件中声明一个类,并创建该类的成员函数,在类声明中实现内联,它使用静态全局变量,例如:

#include <iostream>

static int n = 10;

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

then I see slightly odd behavior under gcc 4.4: 然后我看到gcc 4.4下的一些奇怪的行为:

  1. If I compile without optimization, all uses of the member function use the copy of the variable from one of the translation units (the first one mentioned on the g++ command line). 如果我在没有优化的情况下编译,则成员函数的所有使用都使用来自其中一个翻译单元(g ++命令行中提到的第一个)的变量副本。

  2. If I compile with -O2 , each use of the member function uses the copy of the variable from the translation unit in which the case is made. 如果我使用-O2编译,则每次使用成员函数都会使用来自翻译单元的变量副本。

Obviously this is really bad design, so this question is just out of curiosity. 显然这是一个非常糟糕的设计,所以这个问题只是出于好奇。 But my question, nonetheless, is what does the C++ standard say about this case? 但是,我的问题是,C ++标准对此案例的说法是什么? Is g++ behaving correctly by giving different behavior with and without optimization enabled? 通过在启用和不启用优化的情况下提供不同的行为,g ++是否正常运行?

The standard says (3.2/5): 标准说(3.2 / 5):

There can be more than one definition of a class type (clause 9), ... provided the definitions satisfy the following requirements ... in each definition of D, corresponding names, looked up according to 3.4, shall refer to an entity defined within the definition of D, or shall refer to the same entity 可以有多个类类型的定义(第9节),......如果定义满足以下要求......在D的每个定义中,根据3.4查找的相应名称应引用定义的实体在D的定义内,或应指同一实体

This is where your code loses. 这是您的代码丢失的地方。 The uses of n in the different definitions of Foo do not refer to the same object. Foo的不同定义中使用n不是指同一个对象。 Game over, undefined behavior, so yes gcc is entitled to do different things at different optimization levels. 游戏结束,未定义的行为,所以是的,gcc有权在不同的优化级别做不同的事情。

3.2/5 continues: 3.2 / 5继续:

except that a name can refer to a const object with internal or no linkage if the object has the same integral or enumeration type in all definitions of D, and the object is initialized with a constant expression (5.19), and the value (but not the address) of the object is used, and the object has the same value in all definitions of D 如果对象在D的所有定义中具有相同的整数或枚举类型,并且该对象使用常量表达式(5.19)初始化,并且值(但不是),则名称可以引用具有内部链接或无链接的const对象使用对象的地址),并且对象在D的所有定义中具有相同的值

So in your example code you could make n into a static const int and all would be lovely. 因此,在您的示例代码中,您可以将n转换为static const int并且所有内容都很可爱。 It's not a coincidence that this clause describes conditions under which it makes no difference whether the different TUs "refer to" the same object or different objects - all they use is a compile-time constant value, and they all use the same one. 这个子句描述了不同的TU是否“引用”相同的对象或不同的对象没有区别的条件并不是巧合 - 他们使用的只是编译时常量值,并且它们都使用相同的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM