C ++ struct默认构造函数行为

时间:2014-04-28 07:13:13

标签: c++ struct constructor

据我所知,如果程序员没有实现任何构造函数,编译器会自动生成不执行任何操作的默认构造函数。 我认为它也适用于struct。

我将它用于继承。

struct Parent {
    int a;
};

struct Child : Parent {
    int b;
    Child () {
        printf("child constructor\n");
    }
}

int main () {
    Child c;
    printf("%d\n", c.a);        // c.a = dummy value
    printf("%d\n", c.b);        // c.b = 0
    return 0;
}

在上面的代码中, c.a 是虚拟值。但是,当我更改Child构造函数时,它为零。 唯一的区别是Child在其构造函数中显式调用了父的构造函数。

struct Parent {
    int a;
};

struct Child : Parent {
    int b;
    Child () : Parent () {
        printf("child constructor\n");
    }
}

int main () {
    Child c;
    printf("%d\n", c.a);        // c.a = 0
    printf("%d\n", c.b);        // c.b = 0
    return 0;
}

会发生什么? 我花了一些时间但找不到任何理由。 我使用的编译器是VS2008。 提前谢谢。

2 个答案:

答案 0 :(得分:5)

Parent POD -type(普通旧数据类型)。它没有构造函数或析构函数(除了隐式的,也是微不足道的),复杂的成员等。它只是一个带有标量或其他POD类型成员的结构。当你这样做时:

struct Child : Parent 
{
    int b;
    Child () {
        printf("child constructor\n");
    }
}

你只是在构建子对象。没有Parent的相关构造正在发生。基本类型经历默认初始化

  

C ++11§8.5,第11页

     

如果没有为对象指定初始值设定项,则该对象为默认初始化;如果未执行初始化,则具有自动或动态存储持续时间的对象具有不确定的值。 [注意:具有静态或线程存储持续时间的对象为零初始化,请参见3.6.2。

对于您的POD类型,这意味着:

  

C ++11§8.5,p6

     

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

     
      
  • 如果T是(可能是cv限定的)类类型(第9节),则调用T的默认构造函数(如果T没有可访问的默认构造函数,则初始化是错误的);

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

  •   
  • 否则,不执行初始化。

  •   

但是当你这个时:

struct Child : Parent 
{
    int b;
    Child () : Parent () {
        printf("child constructor\n");
    }
}

发生了不同的事情:您正在调用Parent基类型的值初始化。由于 ()

  

C ++11§8.5,p10

     

一个对象,其初始化程序是一组空的括号,即(),应为值初始化

对于POD类型(其中Parent是一个),值初始化最终将零初始化成员。

  

C ++11§8.5,第7页

     

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

     
      
  • 如果T是具有用户提供的构造函数(12.1)的(可能是cv限定的)类类型(第9节),则调用T的默认构造函数(如果T,初始化是错误的)没有可访问的默认构造函数);

  •   
  • 如果T是(可能是cv限定的)非联合类类型而没有用户提供的构造函数,则该对象零初始化并且,如果T的隐式声明的默认构造函数是非平凡的,则调用该构造函数。

  •   
  • 如果T是数组类型,则每个元素都是值初始化的;

  •   
  • 否则,该对象为零初始化。

  •   

因此a在第二种情况下为零,但在第一种情况下不在。 (好吧,可能在第一个中为零,你真的不能说;它的值是不确定,直到你为它分配某些东西

答案 1 :(得分:2)

根据C ++标准

  

11一个对象,其初始化程序是一组空的括号,即   (),应进行价值初始化。

  

8对T类型的对象进行值初始化意味着: - 如果T是a(可能是   cv-qualified)没有用户提供或删除默认值的类类型   构造函数,然后对象是零初始化

所以在代码片段中

struct Parent {
    int a;
};

struct Child : Parent {
    int b;
    Child () : Parent () {
        printf("child constructor\n");
    }

class Parent初始化为零。其作为数据成员a的标量类型的成员初始化为零。 }