C++ 使用非平凡构造函数初始化联合
我有一个结构,我创建了一个自定义构造函数来将成员初始化为0。我在较旧的编译器中看到,在发布模式下,如果不将memset设置为0,则不会初始化值 我现在想在联合中使用这个结构,但是会出现错误,因为它有一个非平凡的构造函数 因此,问题1。默认编译器实现的构造函数是否保证结构的所有成员都将初始化为null?非平凡构造函数只对“0”的所有成员执行一个成员集,以确保结构干净C++ 使用非平凡构造函数初始化联合,c++,constructor,multiplatform,C++,Constructor,Multiplatform,我有一个结构,我创建了一个自定义构造函数来将成员初始化为0。我在较旧的编译器中看到,在发布模式下,如果不将memset设置为0,则不会初始化值 我现在想在联合中使用这个结构,但是会出现错误,因为它有一个非平凡的构造函数 因此,问题1。默认编译器实现的构造函数是否保证结构的所有成员都将初始化为null?非平凡构造函数只对“0”的所有成员执行一个成员集,以确保结构干净 问题2:如果必须在基本结构上指定构造函数,如何实现联合以包含该元素并确保基本元素初始化为0?可以这样做吗 class Outer {
问题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是标量类型(3.9),则将对象设置为0(零)的值,并转换为T李>
- 如果T是非并集类类型,则每个非静态数据成员和每个基类子对象初始化为零李>
- 如果T是联合类型,则对象的第一个命名数据成员初始化为零强>
- 如果T是数组类型,则每个元素初始化为零李>
- 如果T是引用类型,则不执行初始化
- 它的类没有虚拟函数(10.3)和虚拟基类(10.1),并且
- 它的类的所有直接基类都有平凡的构造函数,并且
- 对于其类中属于类类型(或数组)的所有非静态数据成员 其中),每个这样的类都有一个平凡的构造函数
联合可以有成员函数(包括构造函数和析构函数),但不能有虚函数(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上看到虚拟方法了吗?或任何方法