我有一个结构,我创建一个自定义构造函数来将成员初始化为0。我在较旧的编译器中看到,在发布模式下,如果没有将memset设置为0,则不会初始化值。
我现在想在联合中使用这个结构,但是因为它有一个非平凡的构造函数而得到错误。
那么,问题1.默认编译器实现的构造函数是否保证结构的所有成员都将为null初始化?非平凡的构造函数只是将所有成员的memset设置为'0'以确保结构清晰。
问题2:如果必须在基础结构上指定构造函数,如何实现联合以包含该元素并确保0初始化的基本元素?
答案 0 :(得分:46)
问题1:默认构造函数根据C ++标准将POD成员初始化为0。请参阅下面引用的文字。
问题2:如果必须在基类中指定构造函数,那么该类不能成为联合的一部分。
最后,您可以为联盟提供构造函数:
union U
{
A a;
B b;
U() { memset( this, 0, sizeof( U ) ); }
};
对于Q1:
来自C ++ 03,12.1 Constructors,第190页
隐式定义的默认构造函数执行的初始化集合 将由具有空mem-initializer-list(12.6.2)和空函数体的该类的用户编写的默认构造函数执行的类。
来自C ++ 03,8.5初始化器,第145页
默认初始化T类型的对象意味着:
零初始化T类型的对象意味着:
第二季度:
来自C ++ 03,12.1 Constructors,第190页
如果构造函数是隐式声明的默认构造函数,并且如果:
,则它是微不足道的来自C ++ 03,9.5 Unions,第162页
union可以具有成员函数(包括构造函数和析构函数),但不具有虚函数(10.3)。工会不得有基类。联合不应该用作基类。具有非平凡构造函数(12.1)的类的对象,非平凡的复制构造函数(12.8),非平凡的析构函数(12.4)或非平凡的复制赋值运算符(13.5.3,12.8)不能是联合的成员,也不能是这类对象的数组
答案 1 :(得分:30)
在C ++ 11中,事情变得更好。
您现在可以合法地执行此操作,described by Stroustrup他自己(我从Wikipedia article on 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更详细一点。
答案 2 :(得分:3)
AFAIK工会成员可能没有构造函数或析构函数。
问题1:不,没有这样的保证。任何不在构造函数初始化列表中的POD成员都会进行默认初始化,但这是使用您定义的构造函数,并且具有初始化列表。如果没有定义构造函数,或者定义了没有初始化列表和空体的构造函数,则不会初始化POD成员。
非POD成员将始终通过其默认构造函数构造,如果合成,则再次不会初始化POD成员。鉴于联盟成员可能没有构造函数,您几乎可以保证联盟中结构的POD成员不会被初始化。
问题2:您始终可以像这样初始化结构/联合:
struct foo
{
int a;
int b;
};
union bar
{
int a;
foo f;
};
bar b = { 0 };
答案 3 :(得分:2)
正如Greg Rogers对unwesen帖子的评论中所提到的,你可以给你的联盟一个构造函数(如果你愿意的话也可以使用析构函数):
struct foo
{
int a;
int b;
};
union bar
{
bar() { memset(this, 0, sizeof(*this)); }
int a;
foo f;
};
答案 4 :(得分: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};
}
答案 5 :(得分:-1)
您必须等待编译器支持C ++ 0x才能获得此功能。在那之前,抱歉。