gpt4 book ai didi

c++ - 为什么文件范围静态变量必须被零初始化?

转载 作者:可可西里 更新时间:2023-11-01 17:04:37 28 4
gpt4 key购买 nike

C++ 默认初始化不会将自动存储的变量置零,为什么要对静态存储变量进行特殊处理?

C 和 C++ 定义的东西是否必须与之兼容?如果是这样,为什么 C 决定进行零初始化?

如果一个文件作用域的静态变量提供了一个初始化器,它们将首先被零初始化,然后再次进行常量/动态初始化。那不是多余的吗?例如,以下代码来自 cppreference:http://en.cppreference.com/w/cpp/language/zero_initialization

#include <string>

double f[3]; // zero-initialized to three 0.0's
int* p; // zero-initialized to null pointer value
std::string s; // zero-initialized to indeterminate value
// then default-initialized to ""
int main(int argc, char* argv[])
{
static int n = argc; // zero-initialized to 0
// then copy-initialized to argc
delete p; // safe to delete a null pointer
}

既然如此,为什么n不能直接初始化为argc呢?

编辑:这里的问题已经回答了这个问题的一部分:Static variable initialization?但我不认为这是重复的,因为另一个问题的答案没有回答我的第二个问题,即。为什么 2 阶段初始化。此外,另一篇文章的标题并没有真正说明问题到底是什么。

最佳答案

开发 C 语言的操作系统的行为塑造了这些标准规定。当应用程序加载时,操作系统加载器为 BSS 提供一些内存。 .将其清零是可取的,因为如果其他进程之前使用过该内存,则您正在启动的程序可能会窥探先前进程的内存内容,可能会看到密码、对话或其他数据。不是每个早期或简单的操作系统都关心这个,但大多数都关心,所以在大多数情况下,初始化实际上是“免费”的,因为这是操作系统无论如何都会做的任务。

默认值为 0 使得实现很容易看到在动态初始化期间设置的引用标志,因为不会有未初始化的内存读取和随之而来的未定义行为。例如,给定...

void f() { static int n = g(); }

...编译器/实现也可能隐式添加类似 static bool __f_statics_initialised 变量的东西 - “幸运的是”默认为 0/false 由于归零行为 - 以及类似于(可能是线程安全版本)的初始化代码...

if (!__f_statics_initialised)
{
n = g();
__f_statics_initialised = true;
}

对于上述场景,初始化是在第一次调用时完成的,但对于全局变量,它是在调用 main() 之前的某个时间以未指定的每个对象顺序完成的。在那种情况下,拥有一些特定于对象的初始化代码和动态初始化能够将未初始化状态的静态与他们知道需要设置为非零值的静态区分开来,这使得编写健壮的启动代码变得更加容易。例如,函数可以检查非本地静态指针是否仍为 0,如果是,则为它新建一个对象。

还值得注意的是,许多 CPU 具有高效的指令来清零大量内存。

关于c++ - 为什么文件范围静态变量必须被零初始化?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25742863/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com