[英]zero initialization and static initialization of local scope static variable
我从Google阅读了有关C ++初始化的几篇文章,其中一些将我引到StackOverflow上。 我从这些帖子中挑选的概念如下:
我有一些关于初始化问题的查询( 存储类问题也可能与此有关):
myClass obj = myClass(100);
一样引用初始化myClass obj = myClass(100);
或myClass obj = foo();
我对初始化和存储类说明符问题有太多咨询。 我阅读了C ++ 2003 Standard文档,但找不到清晰的逻辑,因为它们分散在整个文档中。
我希望您能给我一个答案, 从逻辑上解释存储类说明符和初始化的整个过程。 欢迎任何参考!
可以解释我的问题的代码:
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);
}
编辑 :
如果您认为我的问题很繁琐,可以根据上述代码帮助解释您的想法。
我从Google阅读了有关C ++初始化的几篇文章,其中一些将我引到StackOverflow上。 我从这些帖子中挑选的概念如下:
- C ++的初始化顺序为:
- 零初始化 ;
- 静态初始化 ;
- 动态初始化 。
是的,确实有3个阶段(在标准中)。 让我们在继续之前澄清它们:
一个简单的例子:
int const i = 5; // constant initialization
int const j = foo(); // dynamic initialization
- 静态对象 (包括变量)首先被零初始化 ,然后被静态初始化 。
是的,没有。
该标准要求首先将对象初始化为零,然后将它们初始化为:
注意:在进行常量初始化的情况下,编译器可能会遵循as-if规则而忽略第一个零初始化的内存。
我有一些关于初始化问题的查询( 存储类问题也可能与此有关):
- 全局对象 (未使用static关键字定义)也是静态对象,对吗?
是的,在文件范围内, static
对象只是符号的可见性 。 可以从另一个源文件中按名称引用全局对象,而static
对象名称完全位于当前源文件的本地。
混乱源于在许多不同情况下对世界static
的重用:
- 全局对象也像静态对象一样通过上述两个步骤初始化,对吗?
是的,实际上是本地静态对象。
- 什么是静态初始化 ? 它是否涉及初始化静态对象(使用static关键字定义)?
不,如上所述,它是指在不执行用户定义的函数的情况下初始化对象,而是在对象的内存上复制预先计算的字节模式。 请注意,对于稍后将被动态初始化的对象,这只是将内存清零。
- 我还读到了在执行线程首次进入该块时,使用static关键字在块内(即在函数中)定义的对象已初始化! 这意味着本地静态对象不会在执行主函数之前初始化。 这意味着它们没有被初始化为上述两个步骤,对吗?
尽管实际上只有第一次执行通过了它们的定义,但它们是通过两步过程进行初始化的。 因此,过程相同,但时间略有不同。
但是实际上,如果它们的初始化是静态的(即,内存模式是编译时模式)并且不占用其地址,则可以将它们优化。
请注意,在动态初始化的情况下,如果初始化失败(本应初始化它们的函数会抛出异常),则下一次流控制通过它们的定义时,它将重新尝试。
- 动态初始化是指由新操作员创建的对象的初始化,对吗? 它可能像
myClass obj = myClass(100);
一样引用初始化myClass obj = myClass(100);
或myClass obj = foo();
完全不是指需要执行用户定义函数的初始化(注意:就C ++语言而言, std::string
具有用户定义的构造函数)。
编辑:感谢Zach指向我,我错误地称静态初始化为C ++ 11标准称为常量初始化; 现在应该修复此错误。
我相信有三个不同的概念:初始化变量,变量在内存中的位置,变量的初始化时间。
当在内存中分配变量时,典型的处理器会保持不变,因此该变量将具有与其他人之前存储的值相同的值。 为了安全起见,一些编译器添加了额外的代码以初始化其分配为零的所有变量。 我认为这就是您所说的“零初始化”。 当您说:
int i; // not all compilers set this to zero
但是,如果您对编译器说:
int i = 10;
然后编译器指示处理器将10放入内存中,而不是保留旧值或将其设置为零。 我认为这就是您所说的“静态初始化”。
最后,您可以这样说:
int i;
...
...
i = 11;
然后处理器在执行int i;
时会“归零初始化”(或保留旧值) int i;
然后当它到达第i = 11
行时,它会将变量“动态初始化”为11(第一次初始化后可能会发生很长时间。
有:基于堆栈的变量(有时称为静态变量)和内存堆变量(有时称为动态变量)。
可以使用以下方法在堆栈段中创建变量:
int i;
或像这样的内存堆:
int *i = new int;
不同之处在于,退出函数调用后,堆栈段变量丢失,而内存堆变量则保留,直到您说出delete i;
为止delete i;
。 您可以阅读汇编语言书籍以更好地理解它们之间的区别。
当您输入在其中定义的函数调用时,堆栈段变量是“零初始化的”或“静态初始化的”。
当new
操作符首次创建内存堆变量时,该变量将被“零初始化”或“静态初始化”。
您可以考虑一下static int i;
作为一个全局变量,范围仅限于定义它的功能static int i;
之所以会这样,是因为“静态听到”意味着另一件事(退出例程时它不会被破坏,因此它保留了其价值)。 我不确定,但我认为static int i;
的技巧是 是将其放入main()
的堆栈中,这意味着直到您退出整个程序(它保留第一个初始化),它才会被销毁,或者它可能存储在应用程序的数据段中。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.