首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >局部作用域静态变量的零初始化和静态初始化

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

Stack Overflow用户
提问于 2013-07-23 03:35:31
回答 2查看 8.5K关注 0票数 11

我从谷歌上读了几篇关于C++初始化的文章,其中一些文章为我介绍了StackOverflow。我从这些职位中挑选的概念如下:

  • 初始化顺序的C++为:
    1. 零初始化;
    2. 静态初始化;
    3. 动态初始化。

​

  • 静态对象(包括变量)首先是Zero-initialized,,然后是Static-initialized.。

我有几个关于initialization问题的询问(存储类问题也可能相关):

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

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

我希望您给我一个答案,在逻辑上解释存储类说明符和初始化的整个映射。欢迎任何推荐信!

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

代码语言:javascript
复制
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);
}

编辑

如果你认为我的问题很乏味,你可以根据上面的代码帮助解释你的想法。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-07-23 07:12:13

我从谷歌上读了几篇关于C++初始化的文章,其中一些文章为我介绍了StackOverflow。我从这些职位中挑选的概念如下:

  • 初始化顺序的C++为:
    1. 零初始化;
    2. 静态初始化;
    3. 动态初始化。

是的,实际上有三个阶段(在标准中)。让我们先澄清这些问题,然后再继续:

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

一个简单的例子:

代码语言:javascript
复制
int const i = 5;     // constant initialization
int const j = foo(); // dynamic initialization

  • 静态对象(包括变量)首先是Zero-initialized,,然后是Static-initialized.。

是也不是。

标准要求对象首先为零初始化,然后它们是:

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

注意:在常量初始化的情况下,编译器可能会忽略第一个初始化为零的内存,遵循if规则.

我有几个关于initialization问题的询问(存储类问题也可能相关):

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

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

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

  • 全局对象也像静态对象一样按照上面的两个步骤初始化,对吗?

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

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

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

  • 我还读到,当执行线程首先进入块时,使用静态关键字定义的块中定义的对象(即函数中的对象)是初始化的!这意味着本地静态对象在主函数执行之前不会被初始化。这就意味着它们不是像上面提到的两个步骤被初始化的,对吗?

它们是通过这两个步骤过程初始化的,尽管实际上只有第一次执行通过了它们的定义。因此,过程是相同的,但时间是微妙的不同。

然而,在实践中,如果它们的初始化是静态的(即内存模式是编译时模式),并且它们的地址没有被占用,那么它们可能会被优化。

注意,在动态初始化的情况下,如果它们的初始化失败(假设初始化它们的函数会抛出异常),那么在下一次流控制通过它们的定义时,它将被重新尝试。

  • 动态初始化指的是新操作符创建的对象的初始化,对吗?它可能指初始化,如myClass obj = myClass(100);或myClass obj = foo();。

根本没有提到需要执行用户定义函数的初始化(注意:就std::string语言而言,C++有一个用户定义的构造函数)。

编辑:感谢Zach,他指向我,我错误地将静态初始化称为C++11标准所称的常量初始化;这个错误现在应该修复。

票数 22
EN

Stack Overflow用户

发布于 2013-07-23 04:49:51

我相信有三个不同的概念:初始化变量,变量在内存中的位置,变量初始化的时间。

第一:初始化

当在内存中分配变量时,典型的处理器保持内存不变,因此该变量的值将与其他人先前存储的值相同。为了安全起见,一些编译器会添加额外的代码来初始化分配给零的所有变量。我想这就是你所说的“零初始化”的意思。当你说:

代码语言:javascript
复制
 int i; // not all compilers set this to zero

但是,如果您对编译器说:

代码语言:javascript
复制
 int i = 10;

然后编译器指示处理器将10放入内存中,而不是保留旧值或将其设置为零。我想这就是你所说的“静态初始化”的意思。

最后,你可以这样说:

代码语言:javascript
复制
 int i;
 ...
 ...
 i = 11;

然后,处理器在执行int i;时“零初始化”(或保留旧值),然后当它到达行i = 11时,它“动态地初始化”变量为11 (这可能在第一次初始化之后很长时间发生。

第二:变量的位置

有:基于堆栈的变量(有时称为静态变量)和内存堆变量(有时称为动态变量)。

可以使用以下方法在堆栈段中创建变量:

代码语言:javascript
复制
int i;

或者像这样的内存堆:

代码语言:javascript
复制
int *i = new int;

不同的是,堆栈段变量在退出函数调用后丢失,而内存堆变量一直保留到delete i;。你可以读一本汇编语言的书来更好地理解两者的区别。

第三:初始化变量的时间。

当输入函数调用时,堆栈段变量是“零初始化”或静态初始化。

当内存堆变量第一次由new操作符创建时,它是“零初始化”或静态初始化。

最后评论

您可以将static int i;看作是一个全局变量,其作用域仅限于在其中定义的函数。我认为关于static int i;的混淆是因为静态听觉意味着另一件事(当你退出例程时它没有被破坏,所以它保留了它的价值)。我不确定,但我认为用于static int i;的诀窍是将其放入main()堆栈中,这意味着它在退出整个程序之前不会被销毁(因此它保留了第一个初始化),或者它可能存储在应用程序的数据段中。

票数 -4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/17801075

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档