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

时间:2019-02-26 11:31:53

标签: c++

例如:

#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中初始化顺序是固定的,因此上面示例的答案应该不确定。

3 个答案:

答案 0 :(得分:4)

如果要使构造函数成为非内联函数,可以,它将保证是您期望的值。

k将受constant initialization(由于常量初始化程序的影响)的约束,而a的初始化是动态的。所有静态初始化都在静态对象的动态初始化之前发生。但是即使k 是动态初始化的,也可以:

  

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

     

4是否动态初始化是实现定义的   具有静态存储持续时间的非本地非内联变量的值为   在main或main的第一个语句之前排序。 如果   推迟,它很可能在任何非初始化odr-use之前发生   相同中定义的任何非内联函数或非内联变量   转换单位作为要初始化的变量。它是   实现定义在哪个线程中以及在哪个位置   这样的延迟动态初始化程序。

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

但是在您的示例中,c'tor是一个内联函数。因此,仅由于常量初始化而获得666。如果初始化程序不是常量表达式,则a将根据同一TU中的声明顺序在k之前进行动态初始化。

答案 1 :(得分:2)

  

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

取决于。具有静态存储持续时间的所有对象(包括所有静态数据成员)均在main之前初始化。但是,如果您具有静态存储期限的类对象,则可以在静态数据成员之前初始化这些类对象。

  

答案肯定是666

是的

  

引起未定义的行为?

这里没有UB。

  

如果使用不同的单位会发生什么情况

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

答案 2 :(得分:0)

Static成员将获得一个单独的房间。无论是否在创建类的对象之前对其进行初始化,都不会起作用。该程序将在没有undefined行为的情况下运行。

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

  • 创建对象后,您可以获取/设置static成员的值 课
  • 您也可以事先设置。

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