C++ 静态数据成员初始化

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11300652/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 15:01:21  来源:igfitidea点击:

Static Data Member Initialization

c++c++11g++

提问by CyberGuy

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?

为什么静态数据成员(这里是“i”)只是一个声明,而不是一个定义?

回答by Jonathan Wakely

It's important to distinguish the initializerwhich 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 Xyou also create a new X::normalValuevariable. 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.

非静态成员变量存在于它所属的对象内部,因此其地址取决于包含它的对象的地址。每次X创建新X::normalValue变量时,都会创建一个新变量。非静态数据成员的生命周期从类的构造函数开始。NSDMI 语法与变量在内存中的地址没有任何关系,它只允许您在一个地方提供一个初始值,而不是在每个具有显式构造函数初始值设定项列表的构造函数中重复它。

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 externvariable:

你也可以像声明一个extern变量一样看待它:

namespace X {
  extern int i;
}

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

这声明了变量,但程序中的某处必须有一个定义:

int X::i = 0;

回答by AnT

You need to supply a separate definition for a static data member (if its odr-used, as defined in C++11) simply because that definition shall reside somewhere - in one and only one translation unit. Static class data members are basically global objects (global variables) declared in class scope. The compiler wants you to choose a specific translation unit that will hold the actual "body" of each global object. It is you who has to decide which translation unit to place the actual object to.

您需要为静态数据成员(如果其odr-used,如 C++11 中所定义)提供单独的定义,只是因为该定义应驻留在某处 - 在一个且仅一个翻译单元中。静态类数据成员基本上是在类范围内声明的全局对象(全局变量)。编译器希望您选择一个特定的翻译单元来保存每个全局对象的实际“主体”。您必须决定将实际对象放置到哪个翻译单元。

回答by Viktor Latypov

"static" class member is like a globally allocated variable (it is not related to the single class instance), so it must reside in some object file (and to be declared in the ".cpp" file) as a symbol just like any global variable.

“静态”类成员就像一个全局分配的变量(它与单个类实例无关),因此它必须像任何符号一样驻留在某个目标文件中(并在“.cpp”文件中声明)作为符号全局变量。

Simple class member (non-static) resides in the memory block allocated for the class instance.

简单类成员(非静态)驻留在为类实例分配的内存块中。

回答by Jesse Good

The simple reason is because classes are usually declared in headerfiles, which often are included in multiple cpp files. Static data members have external linkage and must be declared in exactly one translation unit which makes them unfit for being defined inside a class.

原因很简单,因为类通常是在文件中声明的,这些文件往往包含在多个 cpp 文件中。静态数据成员具有外部链接,必须在一个翻译单元中声明,这使得它们不适合在类中定义。

As juanchopanza points out the following is allowed:

正如 juanchopanza 指出的那样,允许以下内容:

struct A
{
    const static int i = 1;
};

However, this is only a declarationnot a definition. You still need to define it if you are going to use i's address somewhere. For example:

然而,这只是声明而不是定义。如果您打算在i某处使用的地址,您仍然需要定义它。例如:

f(int);
g(int&);

X<A::i> x; // Okay without definition for template arguments
char a[A::i]; // Okay without definition, just using value as constant expression
&A::i; // Need a definition because I'm taking the address
f(A::i); // Okay without definition for pass by value
g(A::i); // Need a definition with pass by reference

回答by juanchopanza

Bear in mind that is is possible to initialize the static data member at the point of declaration if it is of const integral type of const enumeration type:

请记住,如果静态数据成员是 const 枚举类型的 const 整数类型,则可以在声明点初始化它:

From the C++03 standard, §9.4.2

来自 C++03 标准,第 9.4.2 节

If a static data member is of const integral or const enumeration type, its declaration in the class definition can specify a constant-initializer which shall be an integral constant expression (5.19)

如果静态数据成员是 const 整型或 const 枚举类型,则其在类定义中的声明可以指定一个常量初始化器,它应该是整型常量表达式 (5.19)

struct Foo {
  static const int j = 42; // OK
};

回答by Gigi

When the compiler generate binary code from a unit (extreme simplification: a cpp file and all its included headers) it will emit a symbol for the static variable and eventually initialization code for that variable.

当编译器从一个单元(极端简化:一个 cpp 文件及其所有包含的头文件)生成二进制代码时,它将为静态变量发出一个符号,并最终为该变量发出初始化代码。

It is okay for a static variable symbol to be declared in multiple units, but it is not okay for it to be initialized multiple times.

一个静态变量符号可以在多个单元中声明,但不能多次初始化。

So you must make sure that the initialization code is only emitted for a single unit. This mean that the static variable must be defined in exactly one unit.

因此,您必须确保仅针对单个单元发出初始化代码。这意味着必须在一个单位中定义静态变量。

回答by Heemanshu Bhalla

Static Data Member

静态数据成员

#include<iostream.h>
#include<conio.h>

class static_var
{

static int count; //static member of class
public :

void incr_staticvar()
{
count++;
}

void outputc()
{ 
cout<<"Value of Static variable Count :- "<<count<<endl;
}
};

int static_var::count;

void main()
{
clrscr();
static_var obj1,obj2,obj3,obj4;

obj1.incr_staticvar();
obj2.incr_staticvar();
obj3.incr_staticvar();
obj4.incr_staticvar();

cout<<"\nAfter Increment of static variable by Four Different objects is :-\n";

obj1.outputc ( );
obj2.outputc ( );
obj3.outputc ( );
obj4.outputc ( );

getch();
}