[英]Are static data members initialized before all class objects?
For example: 例如:
#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()
{
}
Is the answer guaranteed to be 666
(I've tested it in gcc8.1.0 the answer is 666
) or causing undefined behavior? 答案保证是
666
(我已经在gcc8.1.0中测试了答案是666
)或导致未定义的行为?
What's more, in this example, object a
and definition A::k
are in the same translation unit, what will happen if they are in different units, since 更重要的是,在这个例子中,对象
a
和定义A::k
在同一个翻译单元中,如果它们在不同的单元中会发生什么,因为
Initialization of static variables in different translation units is indeterminately sequenced
不同翻译单元中的静态变量的初始化是不确定的
From my point of view, since in the same TU the initializaition order is fixed, the answer of the example above should be undfined. 从我的观点来看,由于在相同的TU中初始化顺序是固定的,因此上述示例的答案应该是未定义的。
If you were to make the constructor a non-inline function, yes, it would be guaranteed to be the value you expect. 如果你要使构造函数成为非内联函数,是的,它将保证是你期望的值。
k
will be subject to constant initialization (on account of the constant initializer), while a
's initialization is dynamic. k
将受到恒定初始化 (在帐户中的常量初始化的),而a
的初始化是动态的。 All static initialization happens before dynamic initialization of static objects. 所有静态初始化都在静态对象动态初始化之前发生 But even if
k
was initialized dynamically: 但即使
k
是动态初始化的:
[basic.start.dynamic] (emphasis mine)
[basic.start.dynamic] (强调我的)
4 It is implementation-defined whether the dynamic initialization of a non-local non-inline variable with static storage duration is sequenced before the first statement of main or is deferred.
4实现定义了具有静态存储持续时间的非本地非内联变量的动态初始化是在主要的第一个语句之前还是在延迟之后排序。 If it is deferred, it strongly happens before any non-initialization odr-use of any non-inline function or non-inline variable defined in the same translation unit as the variable to be initialized .
如果它是延迟的,则在任何非初始化odr使用任何非内联函数或非内联变量之前强烈发生,该非内联函数或非内联变量在与要初始化的变量相同的转换单元中定义 。 It is implementation-defined in which threads and at which points in the program such deferred dynamic initialization occurs.
它是实现定义的,其中线程和程序中的哪些点发生延迟动态初始化。
And a non-inline constructor qualifies for such a function. 非内联构造函数有资格使用这样的函数。 This is the basis for the Schwarz Counter technique.
这是Schwarz Counter技术的基础。
But in your example, the c'tor is an inline function. 但在你的例子中,c'tor是一个内联函数。 So it's only due to constant initialization that you get 666. Should the initializer not be a constant expression,
a
would be undergo dynamic initialization before k
according to declaration order in the same TU. 所以这只是由于你得到的常量初始化666.如果初始化器不是常量表达式,则根据同一TU中的声明顺序,
a
将在k
之前进行动态初始化。
Are static data members initialized before all class objects?
静态数据成员是否在所有类对象之前初始化?
Depends. 要看。 All objects with static storage duration, which includes all static data members, are initialised before
main
. 具有静态存储持续时间的所有对象(包括所有静态数据成员)在
main
之前初始化。 But if you have class objects with static storage duration, then those class objects may be initialised before static data members. 但是如果你有具有静态存储持续时间的类对象,那么这些类对象可以在静态数据成员之前初始化。
Is the answer guaranteed to be 666
答案保证是666
Yes. 是。
causing undefined behavior?
导致未定义的行为?
No UB here. 没有UB在这里。
what will happen if they are in different units
如果他们在不同的单位会发生什么
Initialisation of the static member is constant, while the constructor of a
is called during the dynamic initialisation of static objects. 静态成员的初始化是常量,而在静态对象的动态初始化期间调用
a
的构造函数。 Constant initialisation phase is before dynamic phase. 恒定初始化阶段在动态阶段之前。 Thus it doesn't matter in this case whether they are declared in different TU's.
因此,在这种情况下,它们是否在不同的TU中声明并不重要。
Static
member is given a separate room. Static
会员有一个单独的房间。 Whether you initialize it before object creation of the class or not, will not have any effect. 无论是否在创建类的对象之前初始化它都不会产生任何影响。 The program will run without
undefined
behavior. 该程序将运行没有
undefined
行为。
For example In C#, the if the static
member's value is not set, it is given 0
value by the compiler. 例如,在C#中,如果未设置
static
成员的值,则编译器将给出0
值。
static
member after the object creation of the class static
成员的值 After setting it as 666
, other objects made of that class A
will get it value as 666
将其设置为
666
,由该类A
组成的其他对象将其值设为666
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.