为啥在函数体内定义的内置类型的未初始化对象具有未定义的值?

Posted

技术标签:

【中文标题】为啥在函数体内定义的内置类型的未初始化对象具有未定义的值?【英文标题】:Why do uninitialized objects of built-in type defined inside a function body have undefined value?为什么在函数体内定义的内置类型的未初始化对象具有未定义的值? 【发布时间】:2014-11-05 13:24:44 【问题描述】:

问题:为什么在函数体内部定义的未初始化的内置类型的对象有未定义的值,而定义的内置类型的对象任何函数的外部都初始化为0''

举个例子:

#include <iostream>
using std::cout; using std::endl;

int ia[10];                   /* ia has global scope */

int main() 

    int ia2[10];              /* ia2 has block scope */

    for (const auto& i : ia)
        cout << i << " ";     /* Result: 0 0 0 0 0 0 0 0 0 0 */

    cout << endl;
    for (const auto& i : ia2)
        cout << i << " ";     /* Result: 1972896424 2686716 1972303058 8
                                 1972310414 1972310370 1076588592 0 0 0 */
    return 0;

【问题讨论】:

考虑一次初始化全局变量与每次调用函数时初始化局部变量的开销。 这显然是不是重复的(至少不是链接问题)。 OP 不问是否全局内存已初始化,而是为什么,以及为什么局部变量不是,这两个都没有回答在链接的问题中。 【参考方案1】:

因为 C++ 的一般规则之一是不用为不用的东西付费。

初始化全局对象相对便宜,因为它只在程序启动时发生一次。初始化局部变量会增加每个函数调用的开销,这并不是每个人都喜欢的。所以决定让局部变量的初始化是可选的,就像在 C 语言中一样。

顺便说一句,如果你想在函数中初始化你的数组,你可以这样写:

int ia2[10] = 0;

或在 C++11 中:

int ia2[10];

【讨论】:

你可能想提一下堆栈(自动存储的常见实现),以及如何在撤退时将其保持在随机状态,以及在使用上述规则增长时不会必须清除它。【参考方案2】:

在函数外定义的变量在全局范围内。全局变量存储在可执行文件数据段的 BSS 部分。默认情况下,它们在程序启动时直接初始化为零,并且只执行一次。 另一方面,函数中定义的变量存储在堆栈中,每次将其初始化为零将是一个相对昂贵的操作。

查看此链接了解程序的内存布局:Memory Layout 1

请查看此链接以获得很好的解释: Memory Layout 2 引用上面的链接

全局、外部和静态变量默认初始化为零。

【讨论】:

不完全正确。具有静态持续时间的初始化变量(例如int somedata = 42;)将在 .data 段中,并在编译/链接时初始化,因为 .data 段只是映射到内存中。【参考方案3】:

您的问题的答案可以在这里找到http://www.cplusplus.com/doc/tutorial/arrays/

基本上,如果变量是在范围之外定义的,则默认为零初始化。

静态数组,以及直接在命名空间中声明的数组(在任何 函数),总是被初始化。如果没有显式初始化程序 指定,所有元素都默认初始化(零,对于 基本类型)。

这与在作用域内定义的变量进行比较,这些变量未定义为 0。

默认情况下,本地范围的常规数组(例如,那些声明的 在函数内)未初始化。这意味着它的任何一个 元素被设置为任何特定的值;他们的内容是 在声明数组时未确定。

上面的链接实际上解释得很好,我与他们没有任何关系。

【讨论】:

对于您所寻找的内容的误解,我深表歉意。在函数之外,在全局范围内,C++ 给它一个静态存储持续时间。在函数内部或本地范围内,它具有自动存储持续时间。 en.cppreference.com/w/cpp/language/storage_duration

以上是关于为啥在函数体内定义的内置类型的未初始化对象具有未定义的值?的主要内容,如果未能解决你的问题,请参考以下文章

默认初始化

c++ 初始化

NO.4: 确定对象被使用前已被初始化

C语言中函数为啥可以嵌套定义 ?

自动对象&局部静态对象

为啥类型 `Record<string,unknown>` 不接受具有已定义键的对象作为值