2012-08-04 44 views
3

考虑下面的代码:如何初始化一个联合?

struct T { 
    int a; 
    union { 
     struct { 
      int a; 
     } s1; 
     struct { 
      char b[1024]; 
     } s2; 
    }; 
}; 

int main() { 
    T x = T(); 
} 

由于明确的构造函数被调用,上面的代码结束向上零初始化所有数据x中的成员。

但是我想要x初始化,即使明确不被调用。要做到这一点,一个想法就是在声明中初始化数据成员,对于T :: a来说似乎没问题。但是,如何通过使用 相同的标准来初始化工会占用的所有内存?

struct T { 
    int a = 0; 
    union { 
     struct { 
      int a; 
     } s1; 
     struct { 
      char b[1024]; 
     } s2; 
    }; 
}; 

int main() { 
    T x; // I want x to be zero-initialized 
} 
+0

http://stackoverflow.com/questions/1069621/are-members-of-a-c-struct-initialized-to-0-by-default – Joe 2012-08-04 22:51:33

+0

或只是'T x = {};' – Mehrdad 2012-08-04 22:51:46

回答

6

对于联盟没有一个用户定义的默认构造函数,值初始化零初始化

但是,联合的零初始化可能不会使所有内存都为零,而只是填充和第一个成员。如果第一个成员不是最大的,您可能会留下非零的内容。

既然你知道s2是最大的,你可以使归零它默认的构造函数:

struct T 
{ 
    int a; 
    union { 
     int s1a; 
     char s2b[1024]; 
    }; 
    T() : a(), s2b() {} 
}; 

现在

T x; 

将归零。

+0

谢谢。这样T就不再是POD了,对吧? – Martin 2012-08-04 23:07:12

+0

@Martin:不,它不是。但它是“标准布局”。 – 2012-08-04 23:10:34

+0

不只是将{{}'添加到结构{char b [1024];} s2 = {};解决我的问题与工会?在这种情况下int main(){T x; }如果符合联合,则调用所有默认初始化器,标准中的下列内容适用:“ - 如果T是(可能是cv-限定的)类类型(第9章),则调用T的默认构造器 如果T没有可访问的默认构造函数,则初始化格式不正确)“(见8.5.1) – Martin 2012-08-04 23:58:48

6

你可以化零使用memset

memset(&x, 0, sizeof(x)); 
+2

memset?在C++中? – 2012-08-04 22:59:24

+3

在C++中使用memset并不是不合理的。我认为中有一个迭代器,可以用std :: fill以某种方式获得相同的效果,但memset更简单。 – celticminstrel 2014-03-11 21:48:55

2

我建议实行一个构造T

struct T { 
    int a; 
    union { 
     struct { 
      int a; 
     } s1; 
     struct { 
      char b[1024]; 
     } s2; 
    }; 
    T() : a(), s2() {} // <- proper initialisation 
}; 

在这种情况下,我挑中最大的成员你union,因为它是透明的。否则,您可以明确创建union本身。