静态数据成员是否在所有类对象之前初始化?
Are static data members initialized before all class objects?
例如:
#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 中初始化顺序是固定的,所以上面示例的答案应该是无限的。
如果要使构造函数成为非内联函数,是的,它将保证是您期望的值。
k
将受到常量初始化(由于常量初始值设定项),而a
的初始化是动态的。所有静态初始化都发生在静态对象的动态初始化之前。但即使k
是动态初始化的:
[basic.start.dynamic](强调我的)
4 是否动态初始化是实现定义的 具有静态存储持续时间的非局部非内联变量为 在 Main 或 的第一个语句之前排序,或被推迟。如果它 被推迟,它强烈发生在任何非初始化 ODR 使用之前 同一中定义的任何非内联函数或非内联变量 翻译单元作为要初始化的变量。是的 实现定义在哪些线程中以及在哪些点 程序发生这种延迟的动态初始化。
非内联构造函数有资格使用此类函数。这是施瓦茨计数器技术的基础。
但是在您的示例中,c'tor 是一个内联函数。因此,只有由于不断初始化,您才能获得 666。如果初始值设定项不是常量表达式,则a
将在同一 TU 中根据声明顺序进行动态初始化,然后再进行k
。
静态数据成员是否在所有类对象之前初始化?
取决于。所有具有静态存储持续时间的对象(包括所有静态数据成员)都在main
之前初始化。但是,如果您有具有静态存储持续时间的类对象,则这些类对象可能会在静态数据成员之前初始化。
答案保证是666
吗
是的。
导致未定义的行为?
这里没有UB。
如果他们在不同的单位会发生什么
静态成员的初始化是恒定的,而a
的构造函数在静态对象的动态初始化期间调用。常量初始化阶段在动态阶段之前。因此,在这种情况下,它们是否在不同的 TU 中声明并不重要。
Static
成员将获得一个单独的房间。无论是否在类创建对象之前初始化它,都不会有任何影响。程序将在没有undefined
行为的情况下运行。
例如,在 C# 中,如果未设置static
成员的值,则编译器将为其提供0
值。
- 您可以在对象创建后获取/设置
static
成员的值 .class - 正如您已经知道的那样,您也可以在之前设置。
将其设置为666
后,由该类A
组成的其他对象将获得其值666
- 用C++中的CPerson(类)类型的对象初始化STL矢量
- 对象初始化中是否允许指向此成员的指针?
- 对象初始化后在C++中显示 char 数组时的异常行为
- 为什么两种不同的对象初始化方式给出不同的输出
- (2 问题)"类"类型重新定义(即使 #pragma 一次),以及静态函数内的静态成员对象初始化?
- afxmem.cpp中的对象初始化差异
- 删除通过取消引用新对象初始化的对象
- 如何使用sregex_token_iterator对象初始化向量
- 关于默认构造函数,对象初始化/使用C++ OOP
- C++ 基元类型初始化与对象初始化
- 哪个函数负责C++全局范围内的类对象初始化?
- C++中构造函数的对象初始化出现问题
- 如何修复模板 BST 类的对象初始化
- 无法在 QML/C++ 中使用绑定对象初始化 UI
- 为什么参数可以在对象初始化时通过赋值运算符传递给构造函数?
- 类对象初始化的二维向量
- GCC:当层次结构中存在虚拟继承时,C++11 内联对象初始化(使用 "this")不起作用
- 对象初始化
- 类对象初始化
- 使用从另一个类继承的类的对象初始化成员对象