C++ – In-class initialization of static data members

cc++11

In C++, static members may not be initialized in the class body with these exceptions:

  • static members of const integral type can be
  • static members of constexpr literal type must be

Can you explain why these exceptions?

Also, this holds:

Even if a const static data member is initialized in the class body, that member ordinarily should be defined outside the class definition.

This I never understood at all. What's the point of this extra definition?

Just trying to get some intuitions here.

Best Answer

Why can there be an initializer in the class definition?

Concerning the two exceptions for const and constexpr static data members:

[class.static.data]/3

[ Note: In both these cases, the member may appear in constant expressions. — end note ]

I.e. with an initializer, you may use them in constant expressions, e.g.

struct s
{
    static std::size_t const len = 10;
    int arr[len];
};
std::size_t const s::len;

If len wasn't initialized in the class definition, the compiler couldn't easily know its value in the next line to define the length of arr.

One could argue about allowing initializers for of non-const, non-constexpr static data members in the class definition, but this could interfere with the initialization order:

[basic.start.init]/2

Definitions of explicitly specialized class template static data members have ordered initialization. Other class template static data members (i.e., implicitly or explicitly instantiated specializations) have unordered initialization. Other non-local variables with static storage duration have ordered initialization.

That is, the order of the definitions including initializers is important. The order of (dynamic) initialization of non-local objects is only defined within a translation unit, this is another reason why there has to be a definition including initializer for non-const, non-constexpr static data members.


What's the point of this extra definition?

This has already been answered in the comments IMO. You might want to add the ODR, that is, as a name with external linkage, the static data member must (only) be defined in one translation unit (if it's ODR-used). It's up to the programmer to choose this translation unit.