默认初始化和零初始化

3
#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)
}

我目前正在查看参考指南,但有几个问题我不理解。

我已经运行了上面的代码,对于结构体T2,数据成员“int mem”没有出现在初始化列表中。据说t2.mem会被默认初始化为一个不确定的值。 但是当我运行这段代码时,t2.mem似乎被初始化为零?


零是一种可能的不定值,使用该值会导致未定义的行为,还请参见Has C++ standard changed with respect to the use of indeterminate values and undefined behavior in C++14?,以及相关问题Is uninitialized local variable the fastest random number generator? - Shafik Yaghmour
但是当我运行这个代码时,对我来说t2.mem似乎被初始化为零?它可能是0、14、-2323、784等等。为什么要把0单独挑出来作为不可能的不确定值呢?其次,可能是您的编译器(在调试模式下)将该值初始化为0。许多编译器都会这样做,例如Visual Studio。 - PaulMcKenzie
解释为什么我正在使用VS。 - AskJheeze
我期望在Visual Studio的调试模式下,它应该被初始化为0xcccccccc。编辑:我刚在VS2017中测试了一下,t1.memt2.mem都像我预期的那样被初始化为0xcccccccc。这个链接解释了原因:https://dev59.com/GnVC5IYBdhLWcg3w-mZO#127404 - drescherjm
1个回答

5

但当我运行这段代码时,t2.mem 对我来说似乎被初始化为零?

不,对于T1和T2,都没有初始化mem,或者以不确定的值初始化。在这种情况下,构造函数的显式声明不会影响mem的初始化。如果您想要初始化mem,必须在成员初始化列表中明确进行初始化:

struct T2
{
    int mem;
    T2() : mem(0) { }
};

或者通过默认成员初始化器:

struct T1 { int mem = 0; };

或者通过T1的聚合初始化,只有在T1没有任何用户声明的构造函数时才会发生。

struct T1 { int mem; }

int main() {
    T1 a{}; // aggregate initialization
    assert(a.mem == 0)

    T1 b; // default constructor does not value initialize mem
}

如果在第二种情况下看到由0初始化的mem,那么这很可能是编译器的一个特性,或者你刚好运气好得到了0值。这不是标准保证的,不能依赖它。

说实话,我认为你是不正确的。t1和t2具有自动存储并初始化为不确定值。 - AskJheeze
对象t1和t2具有自动存储,子对象继承超对象的生命周期。它们也具有自动存储,并默认初始化为不确定值。 - AskJheeze
@AskJheeze,说实话,我不理解你的想法。是的,t1和t2被初始化为不确定的值,这就是我写的。是的,子对象继承超级对象的生命周期,并默认初始化为不确定的值! - Dmytro Dadyka

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