2
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?

2

2 Answers 2

3

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.

2
  • "static const int: doesn't need to be stored" <-- This is not true. What if you take a pointer to a static const member? To what should the pointer point?
    – cdhowie
    Commented Oct 4, 2014 at 6:37
  • @cdhowie: good point. Last time I tried something like that, I got an undefined symbol linking error, just as you would if you use a non-const one. But, if you never take its address or the moral equivalent, you may get away without defining the storage anywhere. I'm not making value judgements about whether you should, but on common platforms it seems you can. Commented Oct 4, 2014 at 7:17
1

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.

Not the answer you're looking for? Browse other questions tagged or ask your own question.