【问题标题】:Variable initialization in C++C++ 中的变量初始化
【发布时间】:2010-02-07 20:42:47
【问题描述】:

我的理解是int变量会自动初始化为0;然而,事实并非如此。下面的代码打印一个随机值。

int main () 
{   
    int a[10];
    int i;
    cout << i << endl;
    for(int i = 0; i < 10; i++)
        cout << a[i] << " ";
    return 0;
}
  • 哪些规则(如果有)适用于初始化?
  • 具体来说,在什么情况下变量会自动初始化?

【问题讨论】:

    标签: c++ variables initialization


    【解决方案1】:

    会自动初始化

    • 这是一个类/结构实例,其中默认构造函数初始化所有原始类型;喜欢MyClass instance;
    • 您使用数组初始值设定项语法,例如int a[10] = {}(全归零)或int a[10] = {1,2};(除前两项外均归零:a[0] == 1a[1] == 2
    • 同样适用于非聚合类/结构,例如我的类实例 = {}; (更多信息请见here
    • 这是一个全局/外部变量
    • 变量定义为static(无论是在函数内部还是在全局/命名空间范围内)-感谢 Jerry

    永远不要相信一个普通类型的变量(int、long、...)会自动初始化!它可能发生在 C# 等语言中,但不会发生在 C 和 C++ 中。

    【讨论】:

    • 第一点有点不准确。如果它是非 POD 类型,它将被自动初始化。 :)
    • 具有“普通类型”静态存储持续时间的变量也被初始化为零(或空指针,在指针的情况下)。这可能是在函数内声明的 static ,或者是在命名空间范围内(即在任何函数之外)声明的东西。
    • 在第二点中,我建议您明确说明a[0]a[1](最好这样称呼它们)将被初始化为什么。
    • 我的 2 美分 - 关于最后一点'变量被定义为静态' - 变量可能具有静态存储持续时间,但不必定义为静态(即使用 'static' 关键字)。只要在全局范围内拥有任何原始类型,它就会具有“静态存储持续时间”,因此您不需要全局范围内的“静态”关键字来实现它。只有在本地范围内,您才需要“静态”关键字来使局部变量具有“静态存储持续时间”。
    【解决方案2】:

    int 不会初始化为零。当您说int i; 时,您所做的只是为整数保留空间。该位置的值未初始化。仅当您说int i = 0;(或int i = 5;,在这种情况下,值被初始化为5)时才完成。不管怎样,最好将变量初始化为某个已知值。否则,i 在为其保留空间时保存该内存位置的任何随机值。这就是cout 打印出随机值的原因。

    默认值取决于语言的实现。某些语言会将其初始化为一些“正常”的值(可能是 0)。根据经验,我总是将一个变量初始化为一些合理的值(除非我知道在使用它之前我会肯定将它初始化为其他值)。正如我之前提到的,假设价值将是理智的东西是不明智的。它可能是也可能不是(取决于语言,或该语言的解释器/编译器的实现)。

    【讨论】:

      【解决方案3】:

      请参阅第 4.9.5 节 C++ 编程语言的初始化。

      取决于您的变量是本地的、静态的、用户定义的还是 const 默认初始化。

      因为您使用的是 POD(普通旧数据类型),所以 auto 变量没有初始化为任何默认值。

      【讨论】:

        【解决方案4】:

        这篇文章说得最好:http://www.velocityreviews.com/forums/showpost.php?p=1528247&postcount=10

        没有“默认”构造函数 非类类型,但有默认值 (零)初始化。很遗憾, 为了与 C 兼容, 默认初始化未完成 对于以下 POD 类型 情况:

        裸体(即,没有声明 初始化器)局部变量 类或函数。

        动态分配的实例。

        但是,在其他地方(尤其是 静态变量)和在 任何给定空初始化器的东西 参数(当它有效时),得到 默认(零)初始化。

        【讨论】:

        • 我不会说这是因为“与 C 的脑补兼容性”,我认为这更多地与 C++ 的“不为不使用的东西付费”的理念有关。
        【解决方案5】:

        在 C++ 中,自动变量在被明确赋予值之前是未定义的。也许您正在考虑 C# 或其他 .Net 语言或 Java。

        【讨论】:

          【解决方案6】:

          要强制初始化 POD(int 是),您可以使用复制初始化语法:

          #include <iostream>
          
          int main() {
            int i = int();
            int j;
          
            std::cout << "i: " << i << std::endl;
            // warning: undefined behavior
            std::cout << "j: " << j << std::endl;
          }
          

          这属于“只为你使用的东西付费”。如果您随后要为变量赋值,或者可能根本不使用它,则没有理由进行初始化它的工作。为此,您必须明确要求完成该工作。

          【讨论】:

          【解决方案7】:

          不同的操作系统(即 OS X 与 Ubuntu Linux)对 C++ 中未初始化变量和已初始化变量的反应不同。以我的经验,gcc 的 OS X 版本将为以下两个版本的代码编译并打印出 2。就好像我在 Ubuntu Linux 机器上工作一样,第一个代码块将打印出发生在内存位置的变量引用(循环后 + 2)。

              int c;
          
              for( int i = 0; i < 3; i++ )
              {
                  c++;
              }
          
              cout << c << endl; 
          

          其中,它们都会为您提供相同的结果:

              int c = 0;
          
              for( int i = 0; i < 3; i++ )
              {
                  c++;
              }
          
              cout << c << endl; 
          

          【讨论】:

            【解决方案8】:

            除非你自己做,否则局部变量不会被初始化。您看到的是在调用您的方法之前堆栈上的垃圾。

            【讨论】:

              【解决方案9】:

              如果没有为对象指定初始化器,则该对象是默认初始化的;如果不执行初始化,则 具有自动或动态存储期限的对象具有不确定的值。

              标准杆。 8.5,最近的 C++0x 草案 N3092.pdf 的第 11 节,

              http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/

              【讨论】:

                【解决方案10】:

                尽管您最近的发现可能不受欢迎(因为您可能需要初始化一些其他语言会处理的变量),但这可能意味着更少的 cpu 周期,从而更快的代码。

                【讨论】:

                  【解决方案11】:

                  这里int i; 是一个必须手动初始化的自动变量。 在 c 和 c++ 中,auto 变量不会自动初始化。

                  如果你想让编译器初始化它,那么你需要使用以下东西,

                  i 声明为静态变量。

                  static int i; // 编译器将零分配给 i。

                  i 声明为全局变量[在main() 之外]。

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2016-03-11
                    • 2015-04-22
                    • 1970-01-01
                    • 1970-01-01
                    相关资源
                    最近更新 更多