Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Class static variable initialization order

I have a class A which has two static variables. I'd like to initialize one with another, unrelated static variable, just like this:

#include <iostream>
class A
{
public:
    static int a;
    static int b;
};

int A::a = 200;
int a = 100;
int A::b = a;
int main(int argc, char* argv[])
{
    std::cout << A::b << std::endl;

    return 0;
}

The output is 200. So, could anyone tell me why?

like image 307
QuantumPlus Avatar asked Jul 11 '18 07:07

QuantumPlus


People also ask

What is the order of static variable initialization across one program?

C++ guarantees that variables in a compilation unit (. cpp file) are initialised in order of declaration. For number of compilation units this rule works for each one separately (I mean static variables outside of classes). But, the order of initialization of variables, is undefined across different compilation units.

Are static variables initialized first?

Static variables are initialized only once , at the start of the execution. These variables will be initialized first, before the initialization of any instance variables. A single copy to be shared by all instances of the class. A static variable can be accessed directly by the class name and doesn't need any object.

What is the order of initialization for data?

In the initializer list, the order of execution takes place according to the order of declaration of member variables. While using the initializer list for a class in C++, the order of declaration of member variables affects the output of the program. Program 1: C++

How do you initialize a static variable?

For the static variables, we have to initialize them after defining the class. To initialize we have to use the class name then scope resolution operator (::), then the variable name. Now we can assign some value. The following code will illustrate the of static member initializing technique.


3 Answers

That's correct according to the lookup rules. [basic.lookup.unqual]/13 says:

A name used in the definition of a static data member of class X (after the qualified-id of the static member) is looked up as if the name was used in a member function of X. [ Note: [class.static.data] further describes the restrictions on the use of names in the definition of a static data member.  — end note ]

Since the unqualified a is looked up as if you are inside a member function, it must find the member A::a first. The initialization order of A::a and A::b doesn't affect the lookup, though it affects how well defined the result is.

like image 132
StoryTeller - Unslander Monica Avatar answered Oct 14 '22 18:10

StoryTeller - Unslander Monica


So, could anyone tell me why?

This is clearly stated in basic.scope.class/4, emphasis mine:

The potential scope of a declaration that extends to or past the end of a class definition also extends to the regions defined by its member definitions, even if the members are defined lexically outside the class (this includes static data member definitions, nested class definitions, and member function definitions, including the member function body and any portion of the declarator part of such definitions which follows the declarator-id, including a parameter-declaration-clause and any default arguments).

Thus, when you have

int A::a = 200;
int a = 100;
int A::b = a; // note the '::' scope resolution operator
              // OUTPUT: 200

a actually refers to A::a because the class scope is extended by A::b.

Unlike if you have:

int A::a = 200;
int a = 100;
int b = a; // note b is not A::b
           // i.e. without the '::', scope resolution operator
           // OUTPUT: 100

a would refer to the (global) ::a since b here is not a member of class A,
i.e. no class scope extension.

like image 21
Joseph D. Avatar answered Oct 14 '22 17:10

Joseph D.


c++draft/class.static

If an unqualified-id is used in the definition of a static member following the member's declarator-id, and name lookup ([basic.lookup.unqual]) finds that the unqualified-id refers to a static member, enumerator, or nested type of the member's class (or of a base class of the member's class), the unqualified-id is transformed into a qualified-id expression in which the nested-name-specifier names the class scope from which the member is referenced. [ Note: See [expr.prim.id] for restrictions on the use of non-static data members and non-static member functions. — end note ]

It says the unqualified-id is transformed into a qualified-id expression in your situation.

int A::b = a;

You can set qualified-id but has no nested-name-specifier like this.

int A::b = ::a;
like image 38
dao leno Avatar answered Oct 14 '22 16:10

dao leno