Why can't I initialize static members in a class?
The C ++ standard allows you to initialize only static constant integral or enumerated types within a class. For this reason, a allowed to initialize, while others are not.
Reference:
C ++ 03 9.4.2 Static Data Elements
Β§ four
If the static data member is of type const const or const, its declaration in the class definition may indicate an initializer constant, which must be an integral constant expression (5.19). In this case, the term can appear in integral constant expressions. A member still needs to be defined in the namespace area, if used in the program, and the namespace area definition should not contain an initializer.
What are integral types?
C ++ 03 3.9.1 Basic Types
Β§7
The types are bool, char, wchar_t, and signed and unsigned integer types are called integral types. 43) A synonym for an integral type is an integer type.
Footnote:
43) Therefore, transfers (7.2) are not integer; however, enumerations can be translated into int, unsigned int, long or unsigned long, as specified in 4.5.
Workaround:
You can use the enum trick to initialize an array inside your class definition.
class A { static const int a = 3; enum { arrsize = 2 }; static const int c[arrsize] = { 1, 2 }; };
Why does the standard not allow this?
Bjarne explains this aptly here :
A class is usually declared in the header file, and the header file is usually included in many translation units. However, to avoid complex linker rules, C ++ requires each object to have a unique definition. This rule will be violated if C ++ allows the definition of a class in a class, which should be stored in memory as objects.
Why are only static const integral types and enums allowed in-class initialization?
The answer is hidden in Bjarneβs quote, read it carefully,
"C ++ requires that every object has a unique definition. This rule would be violated if C ++ allowed the definition of a class of objects in a class that needed to be stored in memory as objects."
Note that static const integers can be considered as compile-time constants. The compiler knows that the integer value will not change at any time and, therefore, it can apply its own magic and apply optimizations, the compiler simply inserts such members of the class, that is, they are no longer stored in memory, since the need to save in memory is deleted, it gives such variables an exception to the rule mentioned by Bjarne.
It should be noted here that even if the integral values ββof static const can have In-Class Initialization, the use of the address of such variables is unacceptable. You can accept the address of a static member if (and only if) has a definition outside the class. This further confirms the rationale above.
enums are allowed, since values ββof an enumerated type can be used where ints are expected. see quote above
How does this change in C ++ 11?
C ++ 11 mitigates the limitation to a certain extent.
C ++ 11 9.4.2 Static Data Elements
Β§3
If the static data member is of type const literal, its declaration in the class definition may indicate a boolean or equal-initializer, in which each initializer clause, which is an assignment expression, is a constant expression. The static literal data member can be declared in the class definition using the constexpr specifier; if so, its declaration specifies a logical or equal-initializer in which each initializer clause, which is an assignment expression, is a constant expression, [Note. In both cases, the term can be displayed in constant expressions. -end note] A member must still be defined in the namespace scope if used in the program, and the namespace scope definition must not contain an initializer.
In addition, C ++ 11 will allow (Β§12.6.2.8) a non-static data member to be initialized where it is declared (in its class). This will mean very easy user semantics.
Please note that these functions are not yet implemented in the latest gcc 4.7, so you can still get compilation errors.