C++ 使用非平凡构造函数初始化联合

C++ 使用非平凡构造函数初始化联合,c++,constructor,multiplatform,C++,Constructor,Multiplatform,我有一个结构,我创建了一个自定义构造函数来将成员初始化为0。我在较旧的编译器中看到,在发布模式下,如果不将memset设置为0,则不会初始化值 我现在想在联合中使用这个结构,但是会出现错误,因为它有一个非平凡的构造函数 因此,问题1。默认编译器实现的构造函数是否保证结构的所有成员都将初始化为null?非平凡构造函数只对“0”的所有成员执行一个成员集,以确保结构干净 问题2:如果必须在基本结构上指定构造函数,如何实现联合以包含该元素并确保基本元素初始化为0?可以这样做吗 class Outer {

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

我现在想在联合中使用这个结构,但是会出现错误,因为它有一个非平凡的构造函数

因此,问题1。默认编译器实现的构造函数是否保证结构的所有成员都将初始化为null?非平凡构造函数只对“0”的所有成员执行一个成员集,以确保结构干净


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

可以这样做吗

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};
}
…或者像这样

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};
}

AFAIK联合成员不能有构造函数或析构函数

问题1:不,没有这样的保证。任何不在构造函数的初始化列表中的POD成员都会得到默认初始化,但这是使用您定义的构造函数进行的,并且有一个初始值设定项列表。如果您没有定义构造函数,或者您定义的构造函数没有初始值设定项列表和空正文,POD成员将不会初始化

非POD成员将始终通过其默认构造函数进行构造,如果合成该构造函数,也不会初始化POD成员。考虑到联合成员可能没有构造函数,您几乎可以保证联合中结构的POD成员不会被初始化

问题2:您始终可以这样初始化结构/联合:

struct foo
{
    int a;
    int b;
};

union bar
{
    int a;
    foo f;
};

bar b = { 0 };

您必须等待编译器支持C++0x才能获得此结果。在此之前,抱歉。

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

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

最后,您可以为您的工会提供构造函数:

union U 
{
   A a;
   B b;

   U() { memset( this, 0, sizeof( U ) ); }
};
第一季度:

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

隐式定义的默认构造函数执行 类,该类将由用户编写的默认构造函数执行,该类具有空的mem初始值设定项列表(12.6.2)和空的函数体

来自C++03,8.5初始值设定项,第145页

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

  • 如果T是非POD类类型 (第9条),默认构造函数 因为T被称为(和 如果T 没有可访问的默认值 建造商)
  • 如果T是数组类型,则每个元素默认初始化
  • 否则,对象初始化为零
将T类型的对象初始化为零意味着:

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

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

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

  • 它的类没有虚拟函数(10.3)和虚拟基类(10.1),并且
  • 它的类的所有直接基类都有平凡的构造函数,并且
  • 对于其类中属于类类型(或数组)的所有非静态数据成员 其中),每个这样的类都有一个平凡的构造函数
来自C++03,9.5联合体,第162页


联合可以有成员函数(包括构造函数和析构函数),但不能有虚函数(10.3)。并集不应具有基类。联合不得用作基类。具有非平凡构造函数(12.1)、非平凡复制构造函数(12.8)、非平凡析构函数(12.4)或非平凡复制赋值运算符(13.5.3,12.8)的类的对象不能是联合的成员,也不能是格雷格·罗杰斯在其帖子评论中提到的此类对象数组,您可以为您的联合提供构造函数(如果愿意,还可以提供析构函数):


在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*.
};
#包含//放置“新建”所需。
结构点{
点(){}
点(intx,inty):x_ux,y_y{}
int x_uux,y_uux;
};
联合大学{
intz;
双w;
点p;//在C++03中非法;在C++11中合法。
U(){new(&p)Point();}//由于Point成员是构造函数
//定义现在是*必需的*。
};

Stroustrup更详细一点。

我们已经考虑过了,但是我们试图放在联合体中的结构在代码的其他部分中使用,因此删除构造函数(假设编译器将该结构视为POD,并且没有将所有元素初始化为0)可能会破坏依赖于此的代码。你可以给联合体本身一个构造函数,该构造函数将memset自身设置为零。这一点很好!我自己总是忘记工会的建设者!程序员的默认构造函数没有初始值设定项列表和空正文,与编译器生成的构造函数没有区别。@dribeas:谢谢,我写得不太清楚,并相应地更新了我的答案。一个区别是前者使类为非POD,而后者没有。看来我需要一些教育。如果将对象设置为零,是否会删除类虚拟表?@EvilTeach,有两件事,1)您不必使用vtable来实现多态性(除非每个人都这样做)。2) 你在foo上看到虚拟方法了吗?或任何方法