类中静态杆件的构造顺序
construction order of static member in class
#include <iostream>
using namespace std;
class A
{
int x;
public:
A() { cout << "A's constructor called " << endl; }
};
class B
{
static A a;
public:
B() { cout << "B's constructor called " << endl; }
static A getA() { return a; }
};
A B::a;
int main()
{
cout<<"Hin";
B b1;
B b2;
return 0;
}
在这个程序中,我希望输出是
Hi
A's constructor called
B's constructor called
B's constructor called
但输出是
A's constructor called
Hi
B's constructor called
B's constructor called
您看到的行为是正确的,因为main()
和B::a
都位于同一个翻译单元中。从标准中,撇开线程本地初始化的内容,您会看到具有静态存储持续时间的对象动态初始化。该标准确实有如何/何时初始化具有静态存储持续时间的对象的规则:
C++ § 3.6.2 [基本开始]
- 具有静态存储持续时间 (3.7.1( 或线程存储持续时间 (3.7.2( 的变量应在进行任何其他初始化之前初始化 (8.5(。
还有更多处理constexpr
声明,但这不适用于您的代码。所以我们至少知道对象B::a
的内存背景已经初始化为零,但是在这种情况下,构造函数何时真正触发?这称为动态初始化,根据标准:
C++ § 3.6.2 [基本开始]
具有
- 静态存储持续时间的非局部变量的动态初始化是否在
main
的第一条语句之前完成,这是实现定义的。如果初始化推迟到main的第一个语句之后的某个时间点,则应在与要初始化的变量相同的翻译单元中定义的任何函数或变量的第一次odr-use(3.2(之前发生。
在您的情况下,根据情况main()
与B::a
位于同一翻译单元中,为了保持标准,虽然main()
可以在静态存储对象初始化之前开始执行,但main()
本身驻留在翻译单元中,因此所有需要动态初始化的静态存储对象都必须在main()
开始执行之前main()
在同一单元中执行此操作。因此B::a
是在main()
的第一个语句之前构造的。
你为什么要关心?好吧,B::a
总是可以驻留在与main()
不同的翻译单元中(例如:b.cpp
(,并且您的结果可能不同,但仍然符合标准。此时,B::a
是否在开始执行之前动态初始化main()
但同样必须在使用 odr b.cpp
翻译单元中的任何函数或变量之前进行初始化。
相关文章:
- C++编译器是否优化了顺序静态变量读取?
- libavdevice 和 x11 的静态链接库应该以什么顺序链接?
- C++ 模板中的静态常量初始化顺序
- 类静态变量初始化顺序
- 具有静态存储持续时间的常量初始化变量的初始化顺序
- 内联初始化的静态 const 类成员的初始化顺序保证
- 初始化与类类型相同的静态成员(静态初始化顺序问题)
- MSVC 2017 在单个翻译单元中违反静态初始化顺序
- 共享库中静态功能成员的破坏顺序
- 同一函数中的静态函数变量初始化顺序
- 是静态分配的数组的内存分配始终是地址值的顺序
- 静态内联成员初始化顺序
- C++静态初始化顺序:添加到映射中
- C 11指定静态/全局变量的构造顺序
- 静态成员的静态阵列:初始化顺序惨败的可能性
- C++-销毁顺序-函数的静态成员在主类析构函数之前被销毁
- 为什么在定义静态成员变量时不遵循定义顺序
- CRTP自动注册工厂(静态初始化顺序失败)
- C++ 字符串常量和静态初始化顺序惨败
- 共享库中静态对象的销毁顺序