是否保证默认构造函数自动将内置类型初始化为0?

时间:2015-10-30 16:52:50

标签: c++ c++11 initialization language-lawyer default-constructor

在您开始将其标记为重复之前,我已阅读this 但它没有回答我的问题。链接的问题谈到了C ++ 98& C ++ 03但我的问题是关于C ++ 11引入的默认构造函数

考虑以下计划(参见实时演示here):

#include <iostream>
struct Test
{
    int s;
    float m;
    Test(int a,float b) : s(a),m(b)
    { }
    Test()=default;
}t;
int main()
{
    std::cout<<t.s<<'\n';
    std::cout<<t.m<<'\n';
}

我的问题是,编译器提供的默认构造函数总是将内置类型初始化为默认值为0的C ++ 11&amp; C ++ 14当它们是class&amp; struct个成员。这种行为是否由C ++ 11标准保证?

5 个答案:

答案 0 :(得分:14)

这个问题内置了两个不同的问题。

  1. = default对默认构造函数意味着什么?来自[class.ctor]:

      

    默认构造函数是默认的,默认构造函数是默认构造函数,默认构造函数是默认使用的   (3.2)创建其类类型(1.8)的对象,或者在第一次声明后明确默认的对象。隐式定义的默认构造函数执行该类的初始化集合   由该类的用户编写的默认构造函数执行,没有ctor-initializer(12.6.2)和空   化合物语句。

    也就是说,Test() = default完全等同于Test() { },它会默认初始化sm,这会将它们设置为某个不确定的值。

  2. t.st.m如何初始化?是的,这是(1)中的一个单独问题,因为我们不只是在这里调用默认构造函数。来自[basic.stc.static]:

      

    所有没有动态存储持续时间的变量,没有线程存储持续时间,并且是   非本地有静态存储时间。

    和[basic.start.init]:

      

    具有静态存储持续时间(3.7.1)或线程存储持续时间(3.7.2)的变量应为零初始化(8.5)   在进行任何其他初始化之前。

    因此,t.st.m保证为0,即使我们默认构建了本地Test,它们也不会。

答案 1 :(得分:8)

Test = default将默认初始化其成员。 但对于intfloat类型,默认初始化与值初始化

不同

所以

Test t; // t.s and t.m have unitialized value

,而

Test t{}; // t.s == 0 and t.m == 0.0f;

答案 2 :(得分:5)

正如已经回答的那样,无法保证默认构造函数会“将内置类型自动初始化为0”。

您可以使用展示位置来自行查看。请考虑以下代码:

#include <iostream>

struct Test
{
    int s;
    float m;
    Test(int a,float b) : s(a),m(b)
    { }
    Test()=default;
};

int main()
{
    char* buf = new char[sizeof(Test)];
    Test* t = new (buf) Test;

    std::cout << t->s << '\n';
    std::cout << t->m <<'\n';

    t->s = 42;
    t->m = 4.2;

    t->~Test();
    t = new (buf) Test;

    std::cout << t->s << '\n';
    std::cout << t->m <<'\n';
}

如果保证默认构造函数对非类类型的数据成员进行零初始化,则该程序的输出将为四个零。

但是,您可能会看到类似的内容:

0
0
42
4.2

以下是cpp.sh上的代码 - http://cpp.sh/9fdj

答案 3 :(得分:3)

不,默认构造函数不做任何事情! 要初始化成员变量,您可以写:

struct Test
{
    int s = 0;
    float m = 3.3;
    Test(int a,float b) : s(a),m(b)
    { }
    Test()=default;
};

看看这个:C++ ctor = default

答案 4 :(得分:2)

出于所有目的:

Test() = default;

相当于:

Test() {}

因此它不会初始化内置类型的成员。