简体   繁体   English

局部范围静态变量的零初始化和静态初始化

[英]zero initialization and static initialization of local scope static variable

I read several posts on C++ initialization from Google, some of which direct me here on StackOverflow. 我从Google阅读了有关C ++初始化的几篇文章,其中一些将我引到StackOverflow上。 The concepts I picked from those posts are as follows: 我从这些帖子中挑选的概念如下:

  • The order of initialization of C++ is: C ++的初始化顺序为:
    1. Zero Initialization ; 零初始化 ;
    2. Static Initialization ; 静态初始化 ;
    3. Dynamic Initialization . 动态初始化
  • Static objects (variables included) are first Zero-initialized , and then Static-initialized . 静态对象 (包括变量)首先被零初始化 ,然后被静态初始化

I have several inquiries as to the initialization issue ( storage class issue may be related as well): 我有一些关于初始化问题的查询( 存储类问题也可能与此有关):

  • Global objects (defined without static keyword) are also static objects, right? 全局对象 (未使用static关键字定义)也是静态对象,对吗?
  • Global objects are also initialized like static objects by two steps like above, right? 全局对象也像静态对象一样通过上述两个步骤初始化,对吗?
  • What is the Static Initialization ? 什么是静态初始化 Does it refer to initializing static objects (defined with static keyword)? 它是否涉及初始化静态对象(使用static关键字定义)?
  • I also read that objects defined within block (ie in a function) with static keyword is initialized when the execution thread first enters the block! 我还读到了在执行线程首次进入该块时,使用static关键字在块内(即在函数中)定义的对象已初始化! This means that local static objects are not initialized before main function execution. 这意味着本地静态对象不会在执行函数之前初始化。 This means they are not initialized as the two steps mentioned above, right? 这意味着它们没有被初始化为上述两个步骤,对吗?
  • Dynamic initialization refers to initialization of objects created by new operator, right? 动态初始化是指由操作员创建的对象的初始化,对吗? It might refer to initialization like myClass obj = myClass(100); 它可能像myClass obj = myClass(100);一样引用初始化myClass obj = myClass(100); or myClass obj = foo(); myClass obj = foo();

I have too many inquiries on the initialization and storage class specifier issues. 我对初始化和存储类说明符问题有太多咨询。 I read the C++2003 Standard document, but cannot find a clear logic since they are scattered throughout the document. 我阅读了C ++ 2003 Standard文档,但找不到清晰的逻辑,因为它们分散在整个文档中。

I hope you give me an answer that logically explains the whole map of storage class specifier and initialization. 我希望您能给我一个答案, 从逻辑上解释存储类说明符和初始化的整个过程。 Any reference is welcome! 欢迎任何参考!

Code that might explain my question: 可以解释我的问题的代码:

class myClass{
public:
   int i;
   myClass(int j = 10): j(i){}
   // other declarations
};

myClass obj1;//global scope
static myClass obj2(2);//file scope
{   //local scope
   myClass obj3(3);
   static myClass obj4(4);
}

EDIT : 编辑
If you think my question is rather tedious, you can help explain your ideas based on the code above. 如果您认为我的问题很繁琐,可以根据上述代码帮助解释您的想法。

I read several posts on C++ initialization from Google, some of which direct me here on StackOverflow. 我从Google阅读了有关C ++初始化的几篇文章,其中一些将我引到StackOverflow上。 The concepts I picked from those posts are as follows: 我从这些帖子中挑选的概念如下:

  • The order of initialization of C++ is: C ++的初始化顺序为:
    1. Zero Initialization ; 零初始化 ;
    2. Static Initialization ; 静态初始化 ;
    3. Dynamic Initialization . 动态初始化

Yes, indeed there are 3 phases (in the Standard). 是的,确实有3个阶段(在标准中)。 Let us clarify them before continuing: 让我们在继续之前澄清它们:

  • Zero Initialization: the memory is filled with 0s at the byte level. 零初始化:存储器在字节级别填充为0。
  • Constant Initialization: a pre-computed (compile-time) byte pattern is copied at the memory location of the object 常量初始化:将预先计算的(编译时)字节模式复制到对象的内存位置
  • Static Initialization: Zero Initialization followed by Constant Initialization 静态初始化:零初始化,然后进行常量初始化
  • Dynamic Initialization: a function is executed to initialize the memory 动态初始化:执行一个函数来初始化内存

A simple example: 一个简单的例子:

int const i = 5;     // constant initialization
int const j = foo(); // dynamic initialization
  • Static objects (variables included) are first Zero-initialized , and then Static-initialized . 静态对象 (包括变量)首先被零初始化 ,然后被静态初始化

Yes and no. 是的,没有。

The Standard mandates that the objects be first zero-initialized and then they are: 该标准要求首先将对象初始化为零,然后将它们初始化为:

  • constant initialized if possible 如果可能的话,初始化常量
  • dynamically initialized otherwise (the compiler could not compute the memory content at compile-time) 否则动态初始化(编译器无法在编译时计算内存内容)

Note: in case of constant initialization, the compiler might omit to first zero-initialized memory following the as-if rule. 注意:在进行常量初始化的情况下,编译器可能会遵循as-if规则而忽略第一个零初始化的内存。

I have several inquiries as to the initialization issue ( storage class issue may be related as well): 我有一些关于初始化问题的查询( 存储类问题也可能与此有关):

  • Global objects (defined without static keyword) are also static objects, right? 全局对象 (未使用static关键字定义)也是静态对象,对吗?

Yes, at file scope the static object is just about the visibility of the symbol. 是的,在文件范围内, static对象只是符号的可见性 A global object can be referred to, by name, from another source file whilst a static object name is completely local to the current source file. 可以从另一个源文件中按名称引用全局对象,而static对象名称完全位于当前源文件的本地。

The confusion stems from the reuse of the world static in many different situations :( 混乱源于在许多不同情况下对世界static的重用:

  • Global objects are also initialized like static objects by two steps like above, right? 全局对象也像静态对象一样通过上述两个步骤初始化,对吗?

Yes, as are local static objects in fact. 是的,实际上是本地静态对象。

  • What is the Static Initialization ? 什么是静态初始化 Does it refer to initializing static objects (defined with static keyword)? 它是否涉及初始化静态对象(使用static关键字定义)?

No, as explained above it refers to initializing objects without executing a user-defined function but instead copying a pre-computed byte pattern over the object's memory. 不,如上所述,它是指在不执行用户定义的函数的情况下初始化对象,而是在对象的内存上复制预先计算的字节模式。 Note that in the case of objects that will later be dynamically initialized, this is just zero-ing the memory. 请注意,对于稍后将被动态初始化的对象,这只是将内存清零。

  • I also read that objects defined within block (ie in a function) with static keyword is initialized when the execution thread first enters the block! 我还读到了在执行线程首次进入该块时,使用static关键字在块内(即在函数中)定义的对象已初始化! This means that local static objects are not initialized before main function execution. 这意味着本地静态对象不会在执行函数之前初始化。 This means they are not initialized as the two steps mentioned above, right? 这意味着它们没有被初始化为上述两个步骤,对吗?

They are initialized with the two steps process, though indeed only the first time execution pass through their definition. 尽管实际上只有第一次执行通过了它们的定义,但它们是通过两步过程进行初始化的。 So the process is the same but the timing is subtly different. 因此,过程相同,但时间略有不同。

In practice though, if their initialization is static (ie, the memory pattern is a compile-time pattern) and their address is not taken they might be optimized away. 但是实际上,如果它们的初始化是静态的(即,内存模式是编译时模式)并且不占用其地址,则可以将它们优化。

Note that in case of dynamic initialization, if their initialization fails (an exception is thrown by the function supposed to initialize them) it will be re-attempted the next time flow-control passes through their definition. 请注意,在动态初始化的情况下,如果初始化失败(本应初始化它们的函数会抛出异常),则下一次流控制通过它们的定义时,它将重新尝试。

  • Dynamic initialization refers to initialization of objects created by new operator, right? 动态初始化是指由操作员创建的对象的初始化,对吗? It might refer to initialization like myClass obj = myClass(100); 它可能像myClass obj = myClass(100);一样引用初始化myClass obj = myClass(100); or myClass obj = foo(); myClass obj = foo();

Not at all, it refers to initialization requiring the execution of a user defined function (note: std::string has a user-defined constructor as far as the C++ language is concerned). 完全不是指需要执行用户定义函数的初始化(注意:就C ++语言而言, std::string具有用户定义的构造函数)。

EDIT: My thanks to Zach who pointed to me I erroneously called Static Initialization what the C++11 Standard calls Constant Initialization; 编辑:感谢Zach指向我,我错误地称静态初始化为C ++ 11标准称为常量初始化; this error should now be fixed. 现在应该修复此错误。

I believe there are three different concepts: initializing the variable, the location of the variable in memory, the time the variable is initialized. 我相信有三个不同的概念:初始化变量,变量在内存中的位置,变量的初始化时间。

First: Initialization 第一:初始化

When a variable is allocated in memory, typical processors leave the memory untouched, so the variable will have the same value that somebody else stored earlier. 当在内存中分配变量时,典型的处理器会保持不变,因此该变量将具有与其他人之前存储的值相同的值。 For security, some compilers add the extra code to initialize all variables they allocate to zero. 为了安全起见,一些编译器添加了额外的代码以初始化其分配为零的所有变量。 I think this is what you mean by "Zero Initialization". 我认为这就是您所说的“零初始化”。 It happens when you say: 当您说:

 int i; // not all compilers set this to zero

However if you say to the compiler: 但是,如果您对编译器说:

 int i = 10;

then the compiler instructs the processor to put 10 in the memory rather than leaving it with old values or setting it to zero. 然后编译器指示处理器将10放入内存中,而不是保留旧值或将其设置为零。 I think this is what you mean by "Static Initialization". 我认为这就是您所说的“静态初始化”。

Finally, you could say this: 最后,您可以这样说:

 int i;
 ...
 ...
 i = 11;

then the processor "zero initializes" (or leaves the old value) when executing int i; 然后处理器在执行int i;时会“归零初始化”(或保留旧值) int i; then when it reaches the line i = 11 it "dynamically initializes" the variable to 11 (which can happen very long after the first initialization. 然后当它到达第i = 11行时,它会将变量“动态初始化”为11(第一次初始化后可能会发生很长时间。

Second: Location of the variable 第二:变量的位置

There are: stack-based variables (sometimes called static variables), and memory-heap variables (sometimes called dynamic variables). 有:基于堆栈的变量(有时称为静态变量)和内存堆变量(有时称为动态变量)。

Variables can be created in the stack segment using this: 可以使用以下方法在堆栈段中创建变量:

int i;

or the memory heap like this: 或像这样的内存堆:

int *i = new int;

The difference is that the stack segment variable is lost after exiting the function call, while memory-heap variables are left until you say delete i; 不同之处在于,退出函数调用后,堆栈段变量丢失,而内存堆变量则保留,直到您说出delete i;为止delete i; . You can read an Assembly-language book to understand the difference better. 您可以阅读汇编语言书籍以更好地理解它们之间的区别。

Third: The time the variable is initialized 第三:变量初始化的时间

A stack-segment variable is "zero-initialized" or statically-initialized" when you enter the function call they are defined within. 当您输入在其中定义的函数调用时,堆栈段变量是“零初始化的”或“静态初始化的”。

A memory-heap variable is "zero-initialized" or statically-initialized" when it is first created by the new operator. new操作符首次创建内存堆变量时,该变量将被“零初始化”或“静态初始化”。

Final Remark 最后的话

You can think about static int i; 您可以考虑一下static int i; as a global variable with a scope limited to the function it is defined in. I think the confusion about static int i; 作为一个全局变量,范围仅限于定义它的功能static int i; comes because static hear mean another thing (it is not destroyed when you exit the routine, so it retains its value). 之所以会这样,是因为“静态听到”意味着另一件事(退出例程时它不会被破坏,因此它保留了其价值)。 I am not sure, but I think the trick used for static int i; 我不确定,但我认为static int i;的技巧是 is to put it in the stack of main() which means it is not destroyed until you exit the whole program (so it retains the first initialization), or it could be that it is stored in the data segment of the application. 是将其放入main()的堆栈中,这意味着直到您退出整个程序(它保留第一个初始化),它才会被销毁,或者它可能存储在应用程序的数据段中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM