Kam
Kam

Reputation: 6008

Why can one initialize non-const and static const member variables but not static member variables?

struct A
{
    int a = 5;               //OK
    const int b = 5;         //OK 
    static const int c = 5;  //OK 
    static int d = 5;        //Error!
} 



error: ISO C++ forbids in-class initialization of non-const static member 'A::d'

Why is it so? Can someone explain to me the reasoning behind this?

Upvotes: 2

Views: 1404

Answers (2)

AnT stands with Russia
AnT stands with Russia

Reputation: 320401

Initialization of static const member variables is available for integral and enum types. This feature existed in C++ since the first language standard (C++98). It is needed to facilitate usage of static const members in integral constant expressions (i.e. as compile-time constants), which is an important feature of the language. The reason integral and enum types were singled out and treated in this exceptional fashion is that integral constants are often used in compile-time contexts, which require no storage (no definition) for the constant.

The ability to supply initializers for non-static members is a new (for C++11) feature. It is a completely different feature, even though it looks similar at syntax level. Such initializers are used as construction-time initializers for those class members that were not explicitly initialized by the user.

In other words, it is not correct to lump these two features (initializers for static and non-static members) together. These two features are completely different. They are based on completely unrelated internal mechanics. Your question essentially applies the first feature: how come non-const static members cannot be initialized in-class? It is basically a C++98 question and the most likely answer to it is that there was never any reason to treat non-const static members in such an exceptional way. Non-const static members are treated in accordance with the general rules: they require a separate definition and the initializer should be provided at the point of definition.

Upvotes: 1

John Zwinck
John Zwinck

Reputation: 249123

It has to do with where the data is stored. Here's a breakdown:

  • int: member variable, stored wherever the class instance is stored
  • const int: same as int
  • static const int: doesn't need to be stored, it can simply be "inlined" where used
  • static int: this must have a single storage location in the program...where?

Since the static int is mutable, it must be stored in an actual location somewhere, so that one part of the program can modify it and another part can see that modification. But it can't be stored in a class instance, so it must be more like a global variable. So why not just make it a global variable? Well, class declarations are usually in header files, and a header file may be #included in multiple translation units (.cpp files). So effectively the header file says "there is an int...somewhere." But the storage needs to be put into the corresponding .cpp file (like a global variable).

In the end, this is not really about initialization, but rather the storage. You could leave off the initializer and you'd still not have a valid program until you add this to your .cpp file:

int A::d; // initialize if you want to, default is zero

Without this, references to the static int will be undefined and linking will fail.

Upvotes: 3

Related Questions