为什么零初始化不是静态初始化

3
这个话题中,他们说零初始化不是静态初始化。
有人能解释一下为什么吗?
3.6.2/2说:

零初始化和常量初始化一起被称为静态初始化;

这是静态初始化的定义,意味着零初始化是静态初始化,常量初始化也是静态初始化。

这仅适用于非本地变量。零初始化可能发生在其他不是静态的上下文中。 - juanchopanza
原因很简单,因为发表那个答案的人没有提供帮助,我已经因此对该答案进行了负评和评论。 - user743382
@hvd 也许您可以详细说明或提供答案。 - juanchopanza
例如,在函数内部,auto i = int();,或者包含内置类型的聚合体的任何值初始化。 - juanchopanza
@juanchopanza 这仅适用于具有静态生命周期的对象。对象是否为非本地的是另一个问题。 - James Kanze
显示剩余2条评论
4个回答

1
这个答案假设你知道什么是静态存储期。
在C++03中,规定如下(3.6.2):
具有静态存储期(3.7.1)的对象在进行任何其他初始化之前必须进行零初始化(8.5)。零初始化和使用常量表达式进行初始化被称为静态初始化;所有其他初始化都是动态初始化。
实际上,程序有不同的内存段,用于存储具有静态存储期的变量:
一个段通常称为.bss,其中存储所有初始化为零的静态存储变量。
另一个段通常称为.data,其中存储所有显式初始化为值的静态存储变量。
此外,还有一个称为.rodata的段,其中存储所有const变量。
(这些是两个不同的段的原因主要是程序启动性能,您可以在这里阅读更多here。)

零初始化适用于存储在.bss中的所有变量,常量初始化适用于存储在.data中的所有变量。(根据您的系统是基于RAM还是具有真正的ROM,也许常量初始化也适用于.rodata)。

总体而言,所有这些都称为静态初始化,因为它适用于具有静态存储期的对象。


顺便提一下,C的工作方式完全相同,但术语不太正式。我想C++更正式的原因是因为它有构造函数(只是猜测)。 - Lundin
在C语言中,“对于具有静态或线程存储期的对象的初始化器中的所有表达式都应该是常量表达式或字符串字面值。” 这意味着没有动态初始化(这意味着规范可以更简单)。 - James Kanze
动态初始化不是静态初始化。对于从磁盘加载程序映像的系统,具有常量初始化器的数据通常位于.data段中;具有动态初始化器的数据通常位于.bss段中。在我所使用的编译器中,具有常量初始化的const对象位于.text段中。 - James Kanze
@JamesKanze 我注意到在不同的平台上,.rodata.text 的使用并不一致。.text 通常包含实际的可执行代码,所以我猜这取决于编译器是否将常量与代码放在一起。也许我太习惯于使用嵌入式系统了,在这种情况下总是有真正的 ROM 存储器可用:在这种情况下,将常量存储在自己的段中,与代码分开存储更有意义。 - Lundin
@JamesKanze 是的,但通常你希望将const变量存储在另一个物理内存中,比如数据闪存,在运行时可以很容易地进行更新(用户配置等)。 - Lundin

0

这只是词汇问题。初始化有明显的三个阶段(对于具有静态生命周期的变量):零初始化、使用常量表达式进行初始化和动态初始化。当讨论此时,我发现使用术语“静态初始化”来表示第二步很方便(因为它确实在静态情况下进行,不需要执行任何用户编写的代码),即使标准使用了稍微不同的术语。最终,归根结底,它都是一样的:

int a;
int b = 42;
int c = someFunction();

正式地说,这三个变量都将被初始化为零。然后,b 将被初始化为常量表达式 42;很可能它永远不会被零初始化,因为在常量初始化之前,你的代码根本无法看到它。最后,c 将通过调用 someFunction() 进行初始化。

无论定义的顺序如何,这个顺序都是正确的,并且由标准保证。


0

你忘记在这个句子中加上“Together”这个词了,它非常重要。

零初始化 + 常量初始化 = 静态初始化。这样更清晰吗?


你能提供一个静态初始化的示例并解释一下吗? - St.Antario

-2

你链接的帖子说,零初始化不是静态初始化。这是正确的。

这与零初始化不是一种静态初始化非常不同!这是不正确的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接