【问题标题】:Are static data members initialized before all class objects?静态数据成员是否在所有类对象之前初始化?
【发布时间】:2019-02-26 11:31:52
【问题描述】:

例如:

#include<iostream>
using namespace std;
class A
{
    public:
    A(){cout<<k<<endl;}//make some output
    static int k;
};
A a;//before `k`'s definition
int A::k=666;
int main()
{

}

答案是否保证为666(我在gcc8.1.0中测试过答案为666)或导致未定义的行为?

更重要的是,在这个例子中,对象a和定义A::k在同一个翻译单元中,如果它们在不同的单元中会发生什么,因为

不同翻译单元中静态变量的初始化是不定序的

在我看来,由于在同一个TU中初始化顺序是固定的,所以上面例子的答案应该是未定义的。

【问题讨论】:

  • 未定义的行为,多个翻译单元可能发生任何事情。
  • @MatthieuBrucher 如果他们在同一个 TU 怎么办?
  • @MatthieuBrucher 不重复。其实within a single translation unit, initialization of these non-local variables is always sequenced 。但是这个例子似乎遵守了这个规则。
  • @MatthieuBrucher 我问的是类对象和该类的静态成员之间的关系,这是该问题的一个特例。

标签: c++


【解决方案1】:

如果你让构造函数成为一个非内联函数,是的,它会保证是你期望的值。

k 将受制于constant initialization(由于常量初始化器),而a 的初始化是动态的。所有静态初始化都发生在静态对象的动态初始化之前。但即使k 动态初始化:

[basic.start.dynamic](强调我的)

4是否动态初始化由实现定义 具有静态存储持续时间的非局部非内联变量是 在 main 的第一个语句之前排序或被延迟。 如果是 被推迟,它强烈发生在任何非初始化 odr-use 之前 定义在同一文件中的任何非内联函数或非内联变量 翻译单元作为要初始化的变量。这是 实现定义在哪个线程和在哪个点 程序会发生这种延迟的动态初始化。

并且非内联构造函数有资格使用这样的函数。这是Schwarz Counter 技术的基础。

但在您的示例中,c'tor 是一个内联函数。所以只有常量初始化才会得到 666。如果初始化器不是常量表达式,a 将根据同一 TU 中的声明顺序在k 之前进行动态初始化。

【讨论】:

  • 那么如果那个静态成员是动态初始化的,那么例子可能会导致UB?
  • @bigxiao - 嗯,不。如果常量初始化没有发生,那么变量在动态初始化之前被初始化为零。因此,如果 kstd::rand() 之类的东西初始化,这可能会打印 0
  • 但归根结底,这不是你想要搞砸的事情,或者取决于细则。
  • 那么类静态数据成员总是在该类的所有对象之前初始化是真的吗?因为静态初始化总是发生在动态初始化之前?
  • @bigxiao - 谈到 C++,我从不说“总是”。每个例子都需要自己分析。
【解决方案2】:

静态数据成员是否在所有类对象之前初始化?

视情况而定。所有具有静态存储持续时间的对象,包括所有静态数据成员,都在main 之前初始化。但是,如果您有具有静态存储持续时间的类对象,那么这些类对象可能会在静态数据成员之前初始化。

答案是否保证是666

是的。

导致未定义的行为?

这里没有 UB。

如果他们在不同的单位会发生什么

静态成员的初始化是常量,而a的构造函数在静态对象的动态初始化过程中被调用。常量初始化阶段在动态阶段之前。因此,在这种情况下,它们是否在不同的 TU 中声明并不重要。

【讨论】:

    【解决方案3】:

    Static 成员被分配了一个单独的房间。无论您是否在创建类的对象之前对其进行初始化,都不会产生任何影响。该程序将在没有undefined 行为的情况下运行。

    例如在 C# 中,如果 static 成员的值未设置,则编译器会为其赋予 0 值。

    • 您可以在对象创建后获取/设置static成员的值 类
    • 如您所知,您也可以在之前设置。

    将其设置为666后,由该类A构成的其他对象将其值设置为666

    【讨论】:

      猜你喜欢
      • 2018-01-17
      • 2013-04-24
      • 1970-01-01
      • 1970-01-01
      • 2021-04-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-03-31
      相关资源
      最近更新 更多