局部作用域静态变量的零初始化和静态初始化

我从 Google 阅读了几篇关于 C++ 初始化的帖子,其中一些将我引导到 StackOverflow.我从这些帖子中挑选的概念如下:

  • C++ 初始化的顺序是:

    1. 零初始化;
    2. 静态初始化;
    3. 动态初始化.

  • 静态对象(包括变量)首先零初始化,然后静态初始化.

关于初始化问题(存储类问题也可能与此相关),我有几个疑问:

  • 全局对象(没有static关键字定义)也是静态对象,对吧?
  • 全局对象也像静态对象一样通过上述两步初始化,对吗?
  • 什么是静态初始化?它是否指初始化静态对象(用 static 关键字定义)?
  • 我还读到,当执行线程第一次进入块时,使用 static 关键字在块内(即在函数中)定义的对象会被初始化!这意味着本地静态对象在ma??in函数执行之前不会被初始化.这意味着它们没有按照上面提到的两个步骤进行初始化,对吗?
  • 动态初始化是指对new操作符创建的对象进行初始化吧?它可能指的是初始化,如 myClass obj = myClass(100);myClass obj = foo();

我对初始化和存储类说明符问题有太多的疑问.我阅读了 C++2003 标准文档,但由于它们分散在整个文档中,找不到清晰的逻辑.

我希望你给我一个逻辑解释存储类说明符和初始化的整个映射的答案.欢迎任何参考!

可以解释我的问题的代码:

class myClass{上市:国际我;myClass(int j = 10): j(i){}//其他声明};myClass obj1;//全局作用域static myClass obj2(2);//文件作用域{//局部作用域myClass obj3(3);静态 myClass obj4(4);}

<小时>

编辑:
如果你觉得我的问题比较乏味,你可以根据上面的代码帮助解释一下你的想法.

解决方案

我从 Google 阅读了几篇关于 C++ 初始化的帖子,其中一些将我引导到 StackOverflow.我从这些帖子中挑选的概念如下:

  • C++ 初始化的顺序是:

    1. 零初始化;
    2. 静态初始化;
    3. 动态初始化.

是的,确实有 3 个阶段(在标准中).让我们在继续之前澄清它们:

  • 零初始化:内存在字节级别填充为 0.
  • 常量初始化:在对象的内存位置复制预先计算的(编译时)字节模式
  • 静态初始化:零初始化,然后是常量初始化
  • 动态初始化:执行一个函数来初始化内存

一个简单的例子:

int const i = 5;//常量初始化int const j = foo();//动态初始化

<块引用>

  • 静态对象(包括变量)首先零初始化,然后静态初始化.

是和否.

标准要求对象首先进行零初始化,然后是:

  • 尽可能初始化常量
  • 否则动态初始化(编译器无法在编译时计算内存内容)

注意:在常量初始化的情况下,编译器可能会按照 as-if 规则省略第一个零初始化内存.

<块引用>

关于初始化问题(存储类问题也可能与此相关),我有几个疑问:

  • 全局对象(没有static关键字定义)也是静态对象,对吧?

是的,在文件范围内,static 对象只是符号的可见性.全局对象可以通过名称从另一个源文件中引用,而 static 对象名称对于当前源文件来说是完全本地的.

混乱源于在许多不同情况下对世界static的重用:(

<块引用>
  • 全局对象也像静态对象一样通过上述两步初始化,对吗?

是的,事实上本地静态对象也是如此.

<块引用>
  • 什么是静态初始化?它是否指初始化静态对象(用 static 关键字定义)?

不,如上所述,它指的是在不执行用户定义的函数的情况下初始化对象,而是将预先计算的字节模式复制到对象的内存中.请注意,对于稍后将动态初始化的对象,这只是将内存清零.

<块引用>
  • 我还读到,当执行线程第一次进入块时,使用 static 关键字在块内(即在函数中)定义的对象会被初始化!这意味着本地静态对象在ma??in函数执行之前不会被初始化.这意味着它们没有按照上面提到的两个步骤进行初始化,对吗?

它们是用两步过程初始化的,尽管实际上只有第一次执行通过它们的定义.所以过程是一样的,只是时间略有不同.

但实际上,如果它们的初始化是静态的(即,内存模式是编译时模式)并且它们的地址未被占用,它们可能会被优化掉.

请注意,在动态初始化的情况下,如果它们的初始化失败(应该初始化它们的函数抛出异常),它将在下次流控制通过它们的定义时重新尝试.

<块引用>
  • 动态初始化是指对new操作符创建的对象进行初始化吧?它可能指的是初始化,如 myClass obj = myClass(100);myClass obj = foo();

完全不是,它指的是需要执行用户定义函数的初始化(注意:就 C++ 语言而言,std::string 具有用户定义的构造函数).

感谢 Zach 指出我错误地将静态初始化称为 C++11 标准所称的常量初始化;现在应该修复此错误.

I read several posts on C++ initialization from Google, some of which direct me here on StackOverflow. The concepts I picked from those posts are as follows:

  • The order of initialization of C++ is:

    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?
  • 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)?
  • I also read that objects defined within block (i.e. in a function) with static keyword is initialized when the execution thread first enters the block! 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); or 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.

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. The concepts I picked from those posts are as follows:

  • The order of initialization of C++ is:

    1. Zero Initialization;
    2. Static Initialization;
    3. Dynamic Initialization.

Yes, indeed there are 3 phases (in the Standard). Let us clarify them before continuing:

  • Zero Initialization: the memory is filled with 0s at the byte level.
  • 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.

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?

Yes, at file scope the static object is just about the visibility of the symbol. 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.

The confusion stems from the reuse of the world static in many different situations :(

  • 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)?

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 (i.e. in a function) with static keyword is initialized when the execution thread first enters the block! 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); or 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).

EDIT: My thanks to Zach who pointed to me I erroneously called Static Initialization what the C++11 Standard calls Constant Initialization; this error should now be fixed.

相关文章