Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
206 views
in Technique[技术] by (71.8m points)

c++ - Static Data Member Initialization

Why must static data member initialization be outside the class?

class X
{
public:
      int normalValue = 5; //NSDMI
      static int i;
};

int X::i = 0;

Why is the static data member (here "i") only a declaration, not a definition?

Question&Answers:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

It's important to distinguish the initializer which says what its initial value is, and the definition. This modified code is valid, with the initializer in the class definition:

class X
{
public:
  int normalValue = 5;
  static const int i = 0;       // declaration, with initializer
};

const int X::i;                 // definition

i.e. What must be outside the class is a definition, not the initialization.

That's because a variable must have an address in memory (unless it's only used in limited situations, such as in compile-time constant expressions.)

A non-static member variable exists inside the object it is a member of, so its address depends on the address of the object that contains it. Every time you create a new X you also create a new X::normalValue variable. The non-static data member's lifetime begins with the class' constructor. NSDMI syntax doesn't have anything to do with the variable's address in memory, it just allows you to provide an initial value in one place, instead of repeating it in every constructor with an explicit constructor initializer list.

On the other hand, a static member variable is not contained within an instance of the class, it exists independently of any single instance and exists from the start of the program, at a fixed address. In order for a static member variable (or any other global object) to get a unique address the linker must see exactly one definition of the static variable, in exactly one object file, and assign it an address.

Because a static variable needs exactly one definition in exactly one object file, it doesn't make sense to allow that definition to be provided in the class, since class definitions typically exist in header files and are included in multiple object files. So although you can provide an initializer in the class, you still need to define the static data member somewhere.

You can also look at it like declaring an extern variable:

namespace X {
  extern int i;
}

This declares the variable, but there must be a definition somewhere in the program:

int X::i = 0;

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...