Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

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:

  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).

  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.

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? Is g++ behaving correctly by giving different behavior with and without optimization enabled?

like image 546
jchl Avatar asked Mar 07 '11 10:03

jchl


People also ask

Can inline functions have static variables?

Static local variables are not allowed to be defined within the body of an inline function. C++ functions implemented inside of a class declaration are automatically defined inline.

Can we use static variable globally?

A global variable can be accessed from anywhere inside the program while a static variable only has a block scope. So, the benefit of using a static variable as a global variable is that it can be accessed from anywhere inside the program since it is declared globally.

What are global static variables used for?

A global static variable is one that can only be accessed in the file where it is created. This variable is said to have file scope. In C, the preprocessor directive #define was used to create a variable with a constant value. This still works in C++, but problems could arise.

Can we use inline static variable inside class?

In C++ (before C++17 version), we cannot initialize the value of static variables directly in the class. We have to define them outside of the class.


1 Answers

The standard says (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

This is where your code loses. The uses of n in the different definitions of Foo do not refer to the same object. Game over, undefined behavior, so yes gcc is entitled to do different things at different optimization levels.

3.2/5 continues:

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

So in your example code you could make n into a static const int and all would be lovely. 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.

like image 113
Steve Jessop Avatar answered Nov 15 '22 18:11

Steve Jessop