gpt4 book ai didi

c++ - 类中静态成员的构造顺序

转载 作者:行者123 更新时间:2023-11-30 04:00:52 29 4
gpt4 key购买 nike

#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<<"Hi\n";
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 [basic.start.init]

  1. Variables with static storage duration (3.7.1) or thread storage duration (3.7.2) shall be zero-initialized (8.5) before any other initialization takes place.

还有更多关于 constexpr 声明的处理,但这不适用于您的代码。所以我们至少知道对象 B::a 的内存背景已经被零初始化了,好东西,但是在这种情况下构造函数什么时候真正触发?这就是所谓的动态初始化,并且根据标准:

C++ § 3.6.2 [basic.start.init]

  1. It is implementation-defined whether the dynamic initialization of a non-local variable with static storage duration is done before the first statement of main. If the initialization is deferred to some point in time after the first statement of main, it shall occur before the first odr-use (3.2) of any function or variable defined in the same translation unit as the variable to be initialized.

在您的情况下,main()B::a 在同一翻译单元中,与标准保持一致,而 main() 可能会在静态存储对象初始化之前开始执行,main() 本身驻留在翻译单元中,因此所有静态存储在 main() 开始执行之前,需要在与 main() 相同的单元中进行动态初始化的对象必须这样做。因此 B::a 构造在 main() 的第一条语句之前。

为什么要关心?好吧,B::a 总是可以驻留在 main() 不同的 翻译单元中(例如:b.cpp),你的结果可能会有所不同,但仍然符合标准。那时,B::a 是否会在 main() 开始执行之前动态初始化是实现定义的,但是同样,必须b.cpp 翻译单元中的任何函数或变量被 ODR 使用之前初始化。

关于c++ - 类中静态成员的构造顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26071950/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com