结构聚合初始化使用较少的子句,为什么要初始化所有内容?

时间:2014-10-08 11:47:07

标签: c++ initialization list-initialization

如果我有一个常见的linux结构,如:

struct sockaddr_in
{
  sa_family_t    sin_family;   
  in_port_t      sin_port;     
  struct in_addr sin_addr;     

  unsigned char  __pad[__SOCK_SIZE__ - sizeof(short int)
                        - sizeof(unsigned short int) - sizeof(struct in_addr)];
};
#define sin_zero        __pad

我执行聚合初始化:

struct sockaddr_in my_addr = { 0 };

为什么将每个成员初始化为0?

我的意思是:文档说:

  

如果初始化子句的数量小于   成员或初始化子句完全是空的,剩下的   成员由他们的大括号或相等的初始化程序初始化,如果   在类定义中提供,否则(从C ++ 14开始)为空   列表,执行值初始化。

让它变得简单:为什么这段代码打印0?

struct sockaddr_in my_addr = {2, 2}; // initialize sin_family and sin_port to 2, everything else value-initialized

my_addr = {0};

std::cout << my_addr.sin_port; // Why is this 0?

2 个答案:

答案 0 :(得分:2)

draft C++14 standard部分8.5.4 列表初始化中包含了这一点,其中包含:

  

对象或类型T的引用的列表初始化定义如下:

并包括:

  

如果T是聚合,则执行聚合初始化(8.5.1)。

并有以下示例:

struct S2 {
    int m1;
    double m2, m3;
}
S2 s21 = { 1, 2, 3.0 }; // OK
S2 s22 { 1.0, 2, 3 }; // error: narrowing
S2 s23 { }; // OK: default to 0,0,0

8.5.1 聚合,其中包含:

  

如果列表中的初始化子句数少于   聚合成员,然后是每个成员   未明确初始化的应从其初始化   支撑或等于初始化器,或者,如果没有   brace-or-equalinitializer,来自空的初始化列表(8.5.4)。 [   例如:

struct S { int a; const char* b; int c; int d = b[a]; };
S ss = { 1, "asdf" };
     

将ss.a初始化为1,ss.b使用“asdf”,ss.c初始化,值为an   表达式int {}(即0)

请注意8.5.4在C ++ 11中略有不同,它说:

  

对象或类型T的引用的列表初始化定义为   如下:

     
      
  • 如果初始化列表没有元素而T是一个类   使用默认构造函数输入,该对象是值初始化的。

  •   
  • 否则,如果T是聚合,则执行聚合初始化   (8.5.1)。

  •   

答案 1 :(得分:1)

  

为什么将每个成员初始化为0?

因为这是C在初始化结构时所做的事情,而C ++对于兼容性的聚合初始化也是如此。

这样做是因为它更方便(它通常是你想要的那些你没有给出明确价值的会员)而且更安全(它没有这样做)留下危险的未初始化的变量。)

如果你真的希望结构的其他成员保持未初始化,你可以这样做:

struct sockaddr_in s; // entirely uninitialized
s.sin_family = 0;     // only initialize one member