【问题标题】:Why do non-constant static variables need to be initialized outside the class? [duplicate]为什么非常量静态变量需要在类外初始化? [复制]
【发布时间】:2018-06-01 14:55:33
【问题描述】:

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

class A {
    static int x = 0 // compile error;
    static int y;
};

int A::y = 0; // fine

【问题讨论】:

标签: c++ static


【解决方案1】:

本质上是因为x 的存在独立于A实例 数量。

所以x 的存储需要在某个地方定义——你不能依赖A 的实例来做到这一点,这就是

A::x = 0;

在一个翻译单元中,确实如此。

【讨论】:

  • 看起来合乎逻辑,但您可以对静态成员方法使用相同的推理,并且它们仍然可以在类中定义。即使跨多个编译单元获取静态成员方法的地址也会产生相同的地址,因此链接器以某种方式设法“合并”静态成员方法的多个定义。那么为什么静态数据成员的链接器不指向这个呢? (注意:这主要是需要在类外定义,与初始化本身无关)。
  • @Patrick 这可能是引入内联变量的原因之一。
  • 在一个类中定义的@Patrick 成员隐含地是inline... 这个答案可以通过提及 C++17 内联变量来改进。
  • 对于方法来说,允许在多个翻译单元中定义的强烈动机。编译器需要访问定义以内联内容,内联对性能很重要。对于变量,这不太重要。
  • @Ruslan 哎呀,“成员”应该是“方法”。该死的“m”字。
【解决方案2】:

当存在const 限定符时,静态变量可以被视为常量表达式。在类定义中初始化它会产生这种效果。它只是一些常数值,甚至可能不需要任何存储空间。

但在另一种情况下,它不是一个常量表达式。它肯定需要存储。正如@Bathsheba 指出的那样,它只需要在一个翻译单元(C++ 17 之前)中定义。一般来说,包含初始化程序的声明也是一个定义。所以它只是在声明时无法初始化。


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

class A {
  static inline int x = 0;
};

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

【讨论】:

    【解决方案3】:

    经过小小的研究,发现了这个(来自bogotobogo):

    我们不能在类声明中初始化静态成员变量。 这是因为声明是对如何分配内存的描述,但它不分配内存。我们通过使用该格式创建对象来分配和初始化内存。

    在静态类成员的情况下,我们独立初始化静态成员,在类声明之外使用单独的语句。这是因为静态类成员是单独存储的,而不是作为对象的一部分。

    在类声明中初始化静态数据成员的例外情况是静态数据成员是整数或枚举类型的 const。



    我的看法是..

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

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

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

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

    【讨论】:

      【解决方案4】:

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

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

      【讨论】:

      • 我认为大多数人会以不同的方式阅读/解释这句话。我的意思是( struct a { int x=5; } )
      • 嗯,我确实有一个旧的编译器,但你可以马上说,这会为我们俩节省一些时间。
      • 我确实尝试说这么多,但说错了。我的意思是说default member initializer。所以为此我深表歉意。顺便说一句,您可以在在线编译器前端查看此类 sn-ps。
      • 好的,谢谢,会查的。另外,我看到 OP 没有提到他正在使用哪个编译器,所以我想我的帖子并不完全错误(即对于 C++11 之前的编译器)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-11-10
      • 1970-01-01
      • 2023-03-22
      • 1970-01-01
      • 2011-10-06
      • 1970-01-01
      相关资源
      最近更新 更多