31

What is the right way to initialize static data members in C++? I'm also interested in how it has changed from C++98, to C++11 to C++14.

Here is an example:

// bufferedOutput.h
class BufferedOutput
{
 // Static member declaration.
 static long bytecount;
};

// bufferedOutput.cpp
long BufferedOutput::bytecount = 50;

Are there other ways to initialize static data members?

Columbo
  • 60,038
  • 8
  • 155
  • 203
bodacydo
  • 75,521
  • 93
  • 229
  • 319

1 Answers1

37

The rules have always been as follows:

  • A const static data member (SDM) of integral or enumeration type can be initialised in class with a constant expression.

  • A constexpr SDM must be initialised in class with a constant expression.

    C++17 no longer requires an initializer when the default constructor initialises every member. Also, constexpr SDMs are implicitly inline variables, which makes their declaration a definition (external definitions are now deprecated).

  • Other kinds of SDMs can have an initializer at their definition (which is in class if that SDM is declared inline).

Nothing has substantially changed between C++03 and C++11+ for code that is valid in both languages.

Note that for SDMs that are not inline, the in-class declaration is not a definition—regardless of whether an initializer is provided—and they must be defined if they are odr-used.

As of C++17, we can make your SDM inline, which makes its in-class declaration a definition:

class BufferedOutput
{
  static inline long bytecount = 50;
};
Columbo
  • 60,038
  • 8
  • 155
  • 203
  • 2
    You should mention that an out-of-class definition may still be needed even when you can use an in-class initializer. – Jonathan Wakely Oct 30 '14 at 10:22
  • @JonathanWakely I thought thats obvious since the thing in class is always only a declaration (and a definition is needed if the entity is odr-used). – Columbo Oct 30 '14 at 10:24
  • 1
    Unfortunately it's not obvious to lots of people who think that the in-class initializer also provides a definition :-\ Anyway, if allowed to I would give you another +1 now for the final note! – Jonathan Wakely Oct 30 '14 at 11:16
  • to be MISRA compliant the initialiser should be `50L` otherwise you're assigning an integer to long. – Anonymouse Dec 19 '17 at 23:12
  • @Anonymouse `long` is guaranteed to be able to represent any value that `int` can represent. – Columbo Dec 19 '17 at 23:14
  • @Columbo That may bet true, but my point still stands... "MISRA C++2008 5-0-8 - An explicit integral or floating-point conversion shall not increase the size of the underlying type of a cvalue expression." – Anonymouse Dec 20 '17 at 08:56
  • @Anonymouse Appears as if they're talking about explicit conversions. And cvalues (complex values). Which this code has neither of. – Columbo Dec 20 '17 at 10:55