用一个不平凡的构造函数初始化一个联合

我有一个结构,我创build一个自定义的构造函数来初始化成员为0。 我在旧的编译器中看到,在发布模式下,如果不将memset设置为0,则值不会被初始化。

我现在想在联合中使用这个结构,但因为它有一个不平凡的构造函数而得到错误。

所以,问题1.默认的编译器是否实现了构造函数保证一个结构的所有成员都将被初始化为空? 非平凡的构造函数只是将所有成员的memset设置为“0”,以确保结构清晰。

问题2:如果必须在基础结构上指定构造函数,如何实现一个联合来包含该元素并确保初始化的基元素为0?

问题1:默认构造函数根据C ++标准将POD成员初始化为0。 请参阅下面引用的文字。

问题2:如果必须在基类中指定构造函数,那么该类不能成为联合的一部分。

最后,你可以为你的union提供一个构造函数:

union U { A a; B b; U() { memset( this, 0, sizeof( U ) ); } }; 

对于Q1:

从C ++ 03,12.1构造函数,第190页

隐式定义的默认构造函数执行该类的一组初始化,该类将由用户编写的默认构造函数执行,该构造函数具有空的mem-initializer-list(12.6.2)和空的函数体。

从C ++ 03,8.5初始化器,第145页

默认初始化Ttypes的对象意味着:

  • 如果T是一个非POD类types(第9章),则调用T的默认构造函数(如果T没有可访问的默认构造函数,则初始化不合格)。
  • 如果T是数组types,则每个元素都是默认初始化的;
  • 否则,该对象是零初始化的

要初始化Ttypes的对象意味着:

  • 如果T是标量types(3.9),则将该对象设置为转换为T的0(零)值;
  • 如果T是非联合类types,则将每个非静态数据成员和每个基类子对象初始化为零 ;
  • 如果T是联合types,则该对象的第一个命名数据成员将被初始化为零;
  • 如果T是一个数组types,则每个元素都是零初始化的;
  • 如果T是引用types,则不执行初始化。

对于Q2:

从C ++ 03,12.1构造函数,第190页

如果构造函数是一个隐式声明的默认构造函数,并且如果:

  • 它的类没有虚函数(10.3),也没有虚函数类(10.1)
  • 它的类的所有直接基类都有微不足道的构造函数
  • 对于它的类的所有非静态数据成员是类types(或其数组),每个这样的类都有一个简单的构造函数

来自C ++ 03,9.5联盟,第162页

联合可以有成员函数(包括构造函数和析构函数),但不包含虚函数(10.3)。 工会不得有基础class。 一个类的对象有一个不平凡的构造函数(12.1),一个非平凡的拷贝构造函数(12.8),一个非平凡的析构函数(12.4),或者一个非平凡的复制赋值运算符(13.5.3,12.8)不能是联合体的成员,也不能是这样的对象的数组

事情在C ++ 11中变得更好了。

你现在可以像Stroustrup本人所描述的那样合法地做到这一点(我从维基百科关于C ++ 11的文章中得到了这个链接)。

维基百科上的例子如下:

 #include <new> // Required for placement 'new'. struct Point { Point() {} Point(int x, int y): x_(x), y_(y) {} int x_, y_; }; union U { int z; double w; Point p; // Illegal in C++03; legal in C++11. U() {new(&p) Point();} // Due to the Point member, a constructor // definition is now *required*. }; 

Stroustrup进入更多的细节。

AFAIK工会成员可能没有构造函数或析构函数。

问题1:不,没有这样的保证。 任何不在构造函数的初始化列表中的POD成员都会获得默认初始化,但是这与您定义的构造函数有关,并且有一个初始化列表。 如果你没有定义一个构造函数,或者你定义了一个没有初始化列表和空实体的构造函数,POD成员将不会被初始化。

非POD成员将始终通过其默认构造函数构造,如果合成,则不会初始化POD成员。 鉴于工会成员可能没有build造者,你几乎可以保证,工会结构的POD成员不会被初始化。

问题2:你总是可以像这样初始化结构/联合:

 struct foo { int a; int b; }; union bar { int a; foo f; }; bar b = { 0 }; 

正如Greg Rogers对unwesen的post的评论中所提到的,你可以给你的联盟一个构造函数(和析构函数,如果你愿意的话):

 struct foo { int a; int b; }; union bar { bar() { memset(this, 0, sizeof(*this)); } int a; foo f; }; 

你能做这样的事吗?

 class Outer { public: Outer() { memset(&inner_, 0, sizeof(inner_)); } private: union Inner { int qty_; double price_; } inner_; }; 

…或者也许这样的事情?

 union MyUnion { int qty_; double price_; }; void someFunction() { MyUnion u = {0}; } 

编译器必须等待C ++ 0x才能得到这个结果。 在此之前,对不起。