【发布时间】:2018-06-01 14:55:33
【问题描述】:
我知道非常量静态变量需要在类定义之外进行初始化,但是,这是有原因的吗?
class A {
static int x = 0 // compile error;
static int y;
};
int A::y = 0; // fine
【问题讨论】:
-
重复问题很有价值:新问题通常会得到新的答案,这会考虑到技术和语言的现代发展。
我知道非常量静态变量需要在类定义之外进行初始化,但是,这是有原因的吗?
class A {
static int x = 0 // compile error;
static int y;
};
int A::y = 0; // fine
【问题讨论】:
本质上是因为x 的存在独立于A 的实例 数量。
所以x 的存储需要在某个地方定义——你不能依赖A 的实例来做到这一点,这就是
A::x = 0;
在一个翻译单元中,确实如此。
【讨论】:
inline... 这个答案可以通过提及 C++17 内联变量来改进。
当存在const 限定符时,静态变量可以被视为常量表达式。在类定义中初始化它会产生这种效果。它只是一些常数值,甚至可能不需要任何存储空间。
但在另一种情况下,它不是一个常量表达式。它肯定需要存储。正如@Bathsheba 指出的那样,它只需要在一个翻译单元(C++ 17 之前)中定义。一般来说,包含初始化程序的声明也是一个定义。所以它只是在声明时无法初始化。
从 C++17 开始,该变量可以是内联变量。所以定义实际上可以包含在类声明中
class A {
static inline int x = 0;
};
并且编译器会整理出所有这些声明以表示相同的存储。
【讨论】:
经过小小的研究,发现了这个(来自bogotobogo):
我们不能在类声明中初始化静态成员变量。 这是因为声明是对如何分配内存的描述,但它不分配内存。我们通过使用该格式创建对象来分配和初始化内存。
在静态类成员的情况下,我们独立初始化静态成员,在类声明之外使用单独的语句。这是因为静态类成员是单独存储的,而不是作为对象的一部分。
在类声明中初始化静态数据成员的例外情况是静态数据成员是整数或枚举类型的 const。
我的看法是..
静态成员作为类的成员而不是作为类的每个对象中的实例存在。
当您在类声明中初始化静态变量时,作为一个概念,它将在每次创建类的对象/实例时重新初始化(不是实际行为), [因为类声明是构建类的每个新对象的蓝图]。
但是我们知道这不应该是静态成员的行为,所以这个成员的初始化是在类声明之外的。
我发现这个解释更直观,但正式的解释仍然是第一个。
【讨论】:
除了其他人所说的之外,目前在类中没有可以初始化静态成员的位置(C++ 11 之前)(因为成员(静态和非静态都不能在声明的地方初始化)。对于非静态成员,我们使用constructor 或member initializer list 来进行初始化。但这意味着我们必须创建类的实例。
由于静态成员初始化不能依赖于正在创建的实例,它是在声明成员的类之外完成的。
【讨论】: