C++ 什么时候初始化静态和全局变量?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/17783210/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
When are static and global variables initialized?
提问by Zachary
In C++
I know static
and global
objects are constructed before the main
function. But as you know, in C
, there is no such kind initialization procedure
before main
.
据C++
我所知static
,global
对象是在main
函数之前构造的。但是如您所知,在之前C
没有这种类型。initialization procedure
main
For example, in my code:
例如,在我的代码中:
int global_int1 = 5;
int global_int2;
static int static_int1 = 4;
static int static_int2;
- When are these four variables initialized?
- Where values for initialization like
5
and4
are stored during compilation? How to manage them when initialization?
- 这四个变量什么时候初始化?
- 在编译过程中,初始化值如
5
和4
存储在哪里?初始化时如何管理?
EDIT:
Clarification of 2nd question.
编辑:
澄清第二个问题。
- In my code I use
5
to initializeglobal_int1
, so how can the compiler assign5
toglobal_int
? For example, maybe the compiler first store the5
value at somewhere (i.e. a table), and get this value when initialization begins. - As to "How to manage them when initialization?", it is realy vague and I myself does not how to interpret yet. Sometimes, it is not easy to explain a question. Overlook it since I have not mastered the question fully yet.
- 在我
5
用来初始化的代码中global_int1
,编译器如何分配5
给global_int
?例如,也许编译器首先将5
值存储在某处(即表),并在初始化开始时获取该值。 - 至于“初始化时如何管理?”,实在是含糊其辞,我自己也不知道怎么解释。有时,解释一个问题并不容易。忽略它,因为我还没有完全掌握这个问题。
采纳答案by James Kanze
By static and global objects, I presume you mean objects with static lifetime defined at namespace scope. When such objects are defined with local scope, the rules are slightly different.
通过静态和全局对象,我认为您的意思是具有在命名空间范围内定义的静态生命周期的对象。当此类对象定义为局部作用域时,规则略有不同。
Formally, C++ initializes such variables in three phases: 1. Zero initialization 2. Static initialization 3. Dynamic initialization The language also distinguishes between variables which require dynamic initialization, and those which require static initialization: all static objects (objects with static lifetime) are first zero initialized, then objects with static initialization are initialized, and then dynamic initialization occurs.
形式上,C++ 分三个阶段初始化此类变量: 1. 零初始化 2. 静态初始化 3. 动态初始化 该语言还区分需要动态初始化的变量和需要静态初始化的变量:所有静态对象(具有静态生命周期的对象)都是首先零初始化,然后初始化具有静态初始化的对象,然后进行动态初始化。
As a simple first approximation, dynamic initialization means that some code must be executed; typically, static initialization doesn't. Thus:
作为一个简单的第一近似,动态初始化意味着必须执行一些代码;通常,静态初始化不会。因此:
extern int f();
int g1 = 42; // static initialization
int g2 = f(); // dynamic initialization
Another approximization would be that static initialization is what C supports (for variables with static lifetime), dynamic everything else.
另一个近似是静态初始化是 C 支持的(对于具有静态生命周期的变量),其他都是动态的。
How the compiler does this depends, of course, on the initialization, but on disk based systems, where the executable is loaded into memory from disk, the values for static initialization are part of the image on disk, and loaded directly by the system from the disk. On a classical Unix system, global variables would be divided into three "segments":
编译器如何做到这一点当然取决于初始化,但在基于磁盘的系统上,可执行文件从磁盘加载到内存中,静态初始化的值是磁盘上映像的一部分,并由系统直接加载磁盘。在经典的 Unix 系统上,全局变量将被分为三个“段”:
- text:
- The code, loaded into a write protected area. Static variables with `const` types would also be placed here.
- data:
- Static variables with static initializers.
- bss:
- Static variables with no-initializer (C and C++) or with dynamic initialization (C++). The executable contains no image for this segment, and the system simply sets it all to `0` before starting your code.
- 文本:
- 加载到写保护区域的代码。`const` 类型的静态变量也将放置在这里。
- 数据:
- 带有静态初始值设定项的静态变量。
- BS:
- 带有无初始化程序(C 和 C++)或带有动态初始化(C++)的静态变量。可执行文件不包含该段的图像,系统只是在启动代码之前将其全部设置为“0”。
I suspect that a lot of modern systems still use something similar.
我怀疑许多现代系统仍在使用类似的东西。
EDIT:
编辑:
One additional remark: the above refers to C++03. For existing
programs, C++11 probably doesn't change anything, but it does
add constexpr
(which means that some user defined functions
can still be static initialization) and thread local variables,
which opens up a whole new can of worms.
补充一句:以上指的是C++03。对于现有的程序,C++11 可能不会改变任何东西,但它确实增加了constexpr
(这意味着一些用户定义的函数仍然可以是静态初始化)和线程局部变量,这就开辟了一个全新的蠕虫罐。
回答by Kerrek SB
Preface: The word "static" has a vast number of different meanings in C++. Don't get confused.
前言:“静态”一词在 C++ 中有大量不同的含义。不要混淆。
All your objects have static storage duration. That is because they are neither automatic nor dynamic. (Nor thread-local, though thread-local is a bit like static.)
您所有的对象都有静态存储期。那是因为它们既不是自动的也不是动态的。(也不是线程本地的,虽然线程本地有点像静态的。)
In C++, Static objects are initialized in two phases: static initialization, and dynamic initialization.
在 C++ 中,静态对象的初始化分为两个阶段:静态初始化和动态初始化。
Dynamic initialization requires actual code to execute, so this happens for objects that start with a constructor call, or where the initializer is an expression that can only be evaluated at runtime.
Static initialization is when the initializer is known statically and no constructor needs to run. (Static initialization is either zero-initializationor constant-initialization.) This is the case for your
int
variables with constant initializer, and you are guaranteed that those are indeed initialized in the static phase.(Static-storage variables with dynamic initialization are alsozero-initialzed statically before anything else happens.)
动态初始化需要执行实际代码,因此这适用于以构造函数调用开始的对象,或者初始化器是只能在运行时计算的表达式。
静态初始化是当初始化器是静态已知的并且不需要运行构造函数时。(静态初始化是零初始化或常量初始化。)对于
int
具有常量初始化程序的变量就是这种情况,并且您可以保证这些变量确实在静态阶段进行了初始化。(具有动态初始化的静态存储变量也在发生任何其他事情之前静态地初始化为零。)
The crucial point is that the static initialization phase doens't "run" at all. The data is there right from the start. That means that there is no "ordering" or any other such dynamic property that concerns static initialization. The initial values are hard-coded into your program binary, if you will.
关键是静态初始化阶段根本不“运行”。数据从一开始就存在。这意味着没有涉及静态初始化的“排序”或任何其他此类动态属性。如果您愿意,初始值被硬编码到您的程序二进制文件中。
回答by Mike Seymour
When are these four variables initialized?
这四个变量什么时候初始化?
As you say, this happens before program startup, i.e. before main
begins. C does not specify it further; in C++, these happen during the static initialisation phasebefore objects with more complicated constructors or initialisers.
正如你所说,这发生在程序启动之前,即main
开始之前。C 没有进一步说明;在 C++ 中,这些发生在具有更复杂构造函数或初始化程序的对象之前的静态初始化阶段。
Where values for initialization like 5 and 4 are stored during compilation?
编译过程中将初始化值(如 5 和 4)存储在哪里?
Typically, the non-zero values are stored in a data segment in the program file, while the zero values are in a bsssegment which just reserves enough memory for the variables. When the program starts, the data segment is loaded into memory and the bsssegment is set to zero. (Of course, the language standard doesn't specify this, so a compiler could do something else, like generate code to initialise each variables before running main
).
通常,非零值存储在程序文件的数据段中,而零值存储在bss段中,该段仅为变量保留足够的内存。程序启动时,将数据段加载到内存中,并将bss段设置为零。(当然,语言标准没有指定这一点,因此编译器可以做其他事情,例如生成代码以在运行之前初始化每个变量main
)。
回答by scl
Paraphrased from the standard:
转述自标准:
All variables which do not have dynamic storage duration, do not have thread local storage duration, and are not local, have static storage duration. In other words, all globals have static storage duration.
所有没有动态存储期、没有线程本地存储期和非本地的变量都有静态存储期。换句话说,所有全局变量都有静态存储持续时间。
Static objects with dynamic initialization are not necessarily created before the first statement in the main function. It is implementation defined as to whether these objects are created before the first statement in main, or before the first use of any function or variable defined in the same translation unit as the static variable to be initialized.
具有动态初始化的静态对象不一定在主函数中的第一条语句之前创建。实现定义为这些对象是在 main 中的第一条语句之前创建,还是在第一次使用在与要初始化的静态变量相同的翻译单元中定义的任何函数或变量之前创建。
So, in your code, global_int1 and static_int1 are definitely initialized before the first statement in main because they are statically initialized. However, global_int2 and static_int2 are dynamically initialized, so their initialization is implementation defined according to the rule I mentioned above.
因此,在您的代码中, global_int1 和 static_int1 肯定在 main 中的第一条语句之前初始化,因为它们是静态初始化的。但是 global_int2 和 static_int2 是动态初始化的,所以它们的初始化是根据我上面提到的规则定义的实现。
As for your second point, I'm not sure I understand what you mean. Could you clarify?
至于你的第二点,我不确定我理解你的意思。你能澄清一下吗?