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