关于c ++:为什么需要在类外部初始化非常量静态变量?

Why do non-constant static variables need to be initialized outside the class?

本问题已经有最佳答案,请猛点这里访问。

我知道非常量静态变量需要在类定义之外进行初始化,但是,这是有原因的吗?

1
2
3
4
5
6
class A {
    static int x = 0 // compile error;
    static int y;
};

int A::y = 0; // fine


当存在const限定符时,静态变量可以被视为常量表达式。在类定义中初始化它就达到了这个效果。它只是一些常量,甚至不需要任何存储。

但在另一种情况下,它不是一个常量表达式。它确实需要储存。正如@bathsheba指出的,它只需要在一个翻译单元中定义(pre-c++17)。一般来说,包含初始值设定项的声明也是定义。所以它不能在声明时初始化。

从C++ 17开始,该变量可以是内联变量。因此定义实际上可以包含在类声明中

1
2
3
class A {
  static inline int x = 0;
};

编译器将整理所有这些声明以表示相同的存储。


本质上,这是因为x独立于创建的A实例的数量而存在。

因此,x的存储需要在某个地方定义—您不能依赖A的实例来实现这一点,这就是

1
A::x = 0;

就在一个翻译单元里。


经过一个小的研究,发现了这个(来自转向架):

we cannot initialize a static member variable inside the class declaration. That's because the declaration is a description of how memory is to be allocated, but it doesn't allocate memory. We allocate and initialize memory by creating an object using that format.

In the case of a static class member, we initialize the static member independently, with a separate statement outside the class declaration. That's because the static class member is stored separately rather than as part of an object.

The exception to the initialization of a static data member inside the class declaration is if the static data member is a const of integral or enumeration type.

我从这里得到的是……

静态成员作为类的成员而不是类的每个对象中的实例存在。

当初始化类声明中的静态变量时,作为一个概念,它将在每次创建类的对象/实例时重新初始化(而不是实际行为),[因为类声明是构建类的每个新对象的蓝图]。

但是我们知道这不应该是静态成员的行为,所以这个成员的初始化在类声明之外。

我发现这个解释更直观,但正式的解释仍然是第一个。


除了其他人所说的,目前还没有一个地方(预C++ 11)在一个类中,可以初始化一个静态成员(因为静态和非静态的成员不能在声明的地方初始化)。对于非静态成员,我们使用constructormember initializer list进行初始化。但这意味着我们必须创建类的一个实例。

由于静态成员初始化不能依赖于正在创建的实例,因此它是在声明该成员的类之外完成的。