【问题标题】:What are primitive types default-initialized to in C++?C++ 中默认初始化的原始类型是什么?
【发布时间】:2011-04-17 17:14:48
【问题描述】:

当我使用初始化列表时:

struct Struct {
    Struct() : memberVariable() {}
    int memberVariable;
};

原始类型(intboolfloatenum、指针)成员变量是默认初始化的。它获得实现的值是定义的还是所有实现都相同?

【问题讨论】:

    标签: c++ initialization


    【解决方案1】:

    像 int 这样的原生类型通常得到garbage value,例如。无论发生在创建它的内存区域中的什么。但是这在标准中没有定义,它也可能被初始化为 0,这在例如。调试构建。

    编辑。但基本上,你永远不应该相信一个未初始化的变量来保存特定的东西。始终自己定义价值观。

    【讨论】:

    • 否,因为问题中的示例包含memberVariable(),它会初始化它。
    • 这对 C 来说是正确的,但正如标准所说,对 C++ 来说不是。
    • 如果明确默认初始化,它将有一个值。
    【解决方案2】:

    标准说 (8.5/5)

    默认初始化 T 类型的对象意味着:

    ——如果 T 是非 POD 类类型(第 9 条),则调用 T 的默认构造函数(如果没有可访问的默认构造函数,则初始化是非良构的);

    ——如果 T 是一个数组类型,每个元素都是默认初始化的;

    —否则,对象被零初始化

    .

    对 T 类型的对象进行值初始化意味着:

    ——如果 T 是具有用户声明的构造函数 (12.1) 的类类型(第 9 条),则调用 T 的默认构造函数(如果 T 没有可访问的默认构造函数,则初始化是非良构的);

    ——如果 T 是没有用户声明的构造函数的非联合类类型,则 T 的每个非静态数据成员和基类组件都是值初始化的;

    ——如果T是一个数组类型,那么每个元素都是值初始化的;

    ——否则,对象被零初始化

    .

    它获得的值是实现定义的还是所有实现都相同?

    因此,所有实现的值都是相同的。

    Struct 是非 POD 类型所以

     Struct *a =new Struct; // default initialization
    
     //memberVariable will be initialized to 0 because if T is a non-POD class type
     //the default constructor for T is called 
    
     Struct *b = new Struct(); //value initializes Struct, which calls the default ctor.
    
     //memberVariable will be initialized to 0 in this case also.
    

    编辑

    @Johannes 注意到原始类型(int、bool、float、enum、指针)成员变量是 value-initialized 而不是 default initialized

    【讨论】:

    • 优秀的答案。我特别喜欢对标准的引用。 +1
    • 段落中的句子— otherwise, the object is zero-initialized。 6 To default-initialize an object of type T means:是错误的。正确的句子是— otherwise, no initialization is performed.
    • 这在 C++03 中是正确的,但在 C++11 中发生了变化:默认初始化的“否则”情况现在是“不执行初始化”。
    • @PrasoonSaurav 我正在阅读 C++ 入门书,其中提到原始类型的 thp 是默认初始化的,并且它们初始化的值取决于它们定义的位置。如果在函数内部,那么它们用 0 初始化,如果在函数外部,那么它们是未定义的。
    【解决方案3】:

    对于原始类型,默认初始化表示对象被初始化为适合该类型的 0、0.0 或 NULL。

    编辑:以上对 C++98 有效。在 C++03 中,这些术语得到了一些重新定义。现在,使用() 的初始化器(这在语法上只对成员对象可能)会导致值初始化,这对于原始类型意味着存储适当的值0、0.0 或NULL。

    【讨论】:

    • 很好,这里有一些新的 usenet 人 :) 请注意这个默认初始化不适用于他的代码(在 C++03 中)。
    • @Johannes:那只是因为 default initialisation 的定义在 C++98 和 C++03 之间发生了变化。在 C++03 中,memberVariable值初始化,效果完全相同。
    • 值初始化的定义与默认初始化的定义不同。如果memerVariable 是没有用户声明的构造函数的非 POD,则默认初始化不会初始化其成员,而值初始化初始化它们。解释默认初始化的工作原理使人们(包括提问者,他们显然不知道)相信memberVariable 是默认初始化的,而实际上它是值初始化的。
    • @Johannes:请检查 C++98 和 C++03 标准在这方面的区别。术语已重新定义。
    • 我们已经在 SO 上详细阐述了这种差异。见stackoverflow.com/questions/1613341/…。我们有很多关于这个话题的questions and answersfor example here
    【解决方案4】:

    0

    如果您在原语上调用(),效果与分配默认值相同,如果它是静态的。

    【讨论】:

    • AFAIR,静态变量必须显式初始化。我弄错了吗?
    • @DevSolar,“每个静态存储持续时间的对象都应在程序启动时初始化为零,然后再进行任何其他初始化。[注意:在某些情况下,稍后会进行额外的初始化。-结束说明] " 我拥有的标准草案副本的第 8.5 节,第 7 项。
    • 这是否意味着int foo() { return 0; } 保证返回0
    • @Ayxan 会是这样,但我看不出你是如何看待这些相关的。
    • @Ayxan 是的。 int() 产生 0(键入为 int),因此它实际上与 return 0; 相同。
    【解决方案5】:

    这取决于你如何实例化一个类,如果你使用 ClassName(),POD 类默认初始化为零,因为非 POD 类默认构造函数被调用,但如果你使用 ClassName,没有括号,则不会发生默认初始化。

    【讨论】:

    • -1。抱歉,该规则仅适用于具有编译器提供的默认构造函数的类。由于声明了Struct::Struct(),它将同时用于new Structnew Struct()
    【解决方案6】:

    你说的不对。该对象不是默认初始化的,而是值初始化的。而且它的价值是明确的

    int = 0, 
    bool = false, 
    float = 0.0f,  
    enum = (enum type)0, 
    pointer = null pointer
    pointer to member = null member pointer
    

    请注意,零在任何枚举的值范围内,即使它不包含具有该值的显式枚举数,因此将枚举变量初始化为该值是安全的。

    特别是对于指向数据成员的指针,实际使用的表示不是全零位。在至少 GCC 和 Clang 使用的所谓 C++ Itanium ABI 中,指向数据成员的指针具有全一位空表示。

    【讨论】:

    • 对象值是否已初始化(并且默认已初始化),因为它是非 POD 类类型?
    • 它的值初始化不考虑类型。 int 不是非 POD 类类型。
    • 不,我说的是Struct 作为一个整体,这当然是一种非 POD 类型。子对象的值已初始化。
    • @Chubsdad :我在某处读到 C++TC1 明确指出指向成员的指针是 POD。
    • @JohannesSchaub-litb 我正在阅读 C++ 入门书,其中提到原始类型的 thp 是默认初始化的,并且它们初始化的值取决于它们定义的位置。如果在函数内部,则它们使用0 进行初始化,如果在函数外部,则它们是未定义的。
    【解决方案7】:

    具有自动和动态存储持续时间的非类变量的默认初始化会生成具有不确定值的对象(静态和线程局部对象初始化为零)

    引用和 const 标量对象不能默认初始化。 看下面的例子

    #include <string>
     
    struct T1 { int mem; };
     
    struct T2
    {
        int mem;
        T2() { } // "mem" is not in the initializer list
    };
     
    int n; // static non-class, a two-phase initialization is done:
           // 1) zero initialization initializes n to zero
           // 2) default initialization does nothing, leaving n being zero
     
    int main()
    {
        int n;            // non-class, the value is indeterminate
        std::string s;    // class, calls default ctor, the value is "" (empty string)
        std::string a[2]; // array, default-initializes the elements, the value is {"", ""}
    //  int& r;           // error: a reference
    //  const int n;      // error: a const non-class
    //  const T1 t1;      // error: const class with implicit default ctor
        T1 t1;            // class, calls implicit default ctor
        const T2 t2;      // const class, calls the user-provided default ctor
                          // t2.mem is default-initialized (to indeterminate value)
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-10-21
      • 2013-02-19
      • 2017-12-30
      • 1970-01-01
      • 2011-01-28
      • 2013-10-14
      • 2010-12-09
      相关资源
      最近更新 更多