I have a structure which I create a custom constructor to initialize the members to 0's. I've seen in older compilers that when in release mode, without doing a memset to 0, the values are not initialized.
我有一个结构,我创建一个自定义构造函数来将成员初始化为0。我在以前的编译器中看到过,在发布模式下,如果没有将memset设置为0,那么这些值就不会初始化。
I now want to use this structure in a union, but get errors because it has a non-trivial constructor.
我现在想在一个联合中使用这个结构,但是会有错误,因为它有一个非平凡的构造函数。
So, question 1. Does the default compiler implemented constructor guarantee that all members of a structure will be null initialized? The non-trivial constructor just does a memset of all the members to '0' to ensure a clean structure.
所以,问题1。默认编译器实现的构造函数是否保证结构的所有成员都将被初始化?非平凡的构造函数只对所有成员执行一个到'0'的memset,以确保一个干净的结构。
Question 2: If a constructor must be specified on the base structure, how can a union be implemented to contain that element and ensure a 0 initialized base element?
问题2:如果必须在基结构上指定构造函数,那么如何实现联合来包含该元素并确保初始化的基元素为0 ?
6 个解决方案
#1
41
Question 1: Default constructors do initialize POD members to 0 according to the C++ standard. See the quoted text below.
问题1:默认构造函数根据c++标准将POD成员初始化为0。参见下面的引用文本。
Question 2: If a constructor must be specified in a base class, then that class cannot be part of a union.
问题2:如果一个构造函数必须在基类中指定,那么这个类就不能是联合的一部分。
Finally, you can provide a constructor for your union:
最后,您可以为您的工会提供一个构造函数:
union U
{
A a;
B b;
U() { memset( this, 0, sizeof( U ) ); }
};
For Q1:
Q1:
From C++03, 12.1 Constructors, pg 190
从c++ 03, 12.1构造函数,pg 190
The implicitly-defined default constructor performs the set of initializations of the class that would be performed by a user-written default constructor for that class with an empty mem-initializer-list (12.6.2) and an empty function body.
隐含定义的默认构造函数执行类的初始化集,该类由用户编写的默认构造函数执行,该构造函数具有一个空的mem-initializer-list(12.6.2)和一个空的函数体。
From C++03, 8.5 Initializers, pg 145
从c++ 03, 8.5初始化器,pg 145
To default-initialize an object of type T means:
默认初始化类型为T的对象意味着:
- if T is a non-POD class type (clause 9), the default constructor for T is called (and the initialization is ill-formed if T has no accessible default constructor);
- 如果T是一种非pod类类型(第9条),则调用T的默认构造函数(如果T没有可访问的默认构造函数,则初始化是病态的);
- if T is an array type, each element is default-initialized;
- 如果T是数组类型,则每个元素都是默认初始化的;
- otherwise, the object is zero-initialized.
- 否则,对象是零初始化的。
To zero-initialize an object of type T means:
零初始化类型为T的对象意味着:
- if T is a scalar type (3.9), the object is set to the value of 0 (zero) converted to T;
- 如果T是标量类型(3.9),则将对象设置为转换为T的0 (0);
- if T is a non-union class type, each non static data member and each base-class subobject is zero-initialized;
- 如果T是一个非union类类型,则每个非静态数据成员和每个base类subobject都是零初始化的;
- if T is a union type, the object’s first named data member is zero-initialized;
- 如果T是一个联合类型,则对象的第一个命名数据成员为零初始化;
- if T is an array type, each element is zero-initialized;
- 如果T是数组类型,则每个元素都是零初始化的;
- if T is a reference type, no initialization is performed.
- 如果T是引用类型,则不执行初始化。
For Q2:
Q2:
From C++03, 12.1 Constructors, pg 190
从c++ 03, 12.1构造函数,pg 190
A constructor is trivial if it is an implicitly-declared default constructor and if:
如果构造函数是隐式声明的默认构造函数,并且如果:
- its class has no virtual functions (10.3) and no virtual base classes (10.1), and
- 它的类没有虚函数(10.3),也没有虚基类(10.1),并且
- all the direct base classes of its class have trivial constructors, and
- 它的类的所有直接基类都有普通的构造函数
- for all the nonstatic data members of its class that are of class type (or array thereof), each such class has a trivial constructor
- 对于类类型(或其数组)的类的所有非静态数据成员,每个此类类都有一个普通的构造函数
From C++03, 9.5 Unions, pg 162
从c++ 03, 9.5联盟,第162页
A union can have member functions (including constructors and destructors), but not virtual (10.3) functions. A union shall not have base classes. A union shall not be used as a base class.An object of a class with a non-trivial constructor (12.1), a non-trivial copy constructor (12.8), a non-trivial destructor (12.4), or a non-trivial copy assignment operator (13.5.3, 12.8) cannot be a member of a union, nor can an array of such objects
联合可以有成员函数(包括构造函数和析构函数),但不能有虚函数(10.3)。工会不得有基类。联盟不应被用作基类。一个具有非平凡构造函数(12.1)的类的对象,一个非平凡的复制构造函数(12.8),一个非平凡的解构函数(12.4),或者一个非平凡的复制赋值运算符(13.5.3,12.8)不能是一个联合的成员,也不能是这样的对象数组。
#2
24
Things changed for the better in C++11.
在c++ 11中,情况变得更好了。
You can now legally do this, as described by Stroustrup himself (I reached that link from the Wikipedia article on C++11).
您现在可以合法地这样做,就像Stroustrup自己描述的那样(我从Wikipedia关于c++ 11的文章中找到了这个链接)。
The example on Wikipedia is as follows:
*上的例子如下:
#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 goes into a little more detail.
Stroustrup讲得更详细一些。
#3
3
AFAIK union members may not have constructors or destructors.
AFAIK联盟成员可能没有构造函数或析构函数。
Question 1: no, there's no such guarantee. Any POD-member not in the constructor's initialization list gets default-initialized, but that's with a constructor you define, and has an initializer list. If you don't define a constructor, or you define a constructor without an initializer list and empty body, POD-members will not be initialized.
问题1:不,没有这样的保证。任何不在构造函数的初始化列表中的pod成员都将被默认初始化,但这是您定义的构造函数,并具有初始化列表。如果没有定义构造函数,或者定义没有初始化器列表和空主体的构造函数,那么pod成员将不会被初始化。
Non-POD members will always be constructed via their default constructor, which if synthesized, again would not initialize POD-members. Given that union members may not have constructors, you'd pretty much be guaranteed that POD-members of structs in a union will not be initialized.
非pod成员将始终通过它们的默认构造函数来构造,如果合成了这些构造函数,也不会初始化pod成员。考虑到union成员可能没有构造函数,您将几乎得到保证,不会初始化union中结构体的POD-members。
Question 2: you can always initialize structures/unions like so:
问题2:你可以像这样初始化结构/联合:
struct foo
{
int a;
int b;
};
union bar
{
int a;
foo f;
};
bar b = { 0 };
#4
2
As mentioned in Greg Rogers' comment to unwesen's post, you can give your union a constructor (and destructor if you wish):
正如Greg Rogers对unwesen的文章所提到的那样,您可以给您的union一个构造函数(如果您希望的话,也可以是析构函数):
struct foo
{
int a;
int b;
};
union bar
{
bar() { memset(this, 0, sizeof(*this)); }
int a;
foo f;
};
#5
0
Can you do something like this?
你能做这样的事吗?
class Outer
{
public:
Outer()
{
memset(&inner_, 0, sizeof(inner_));
}
private:
union Inner
{
int qty_;
double price_;
} inner_;
};
...or maybe something like this?
…或者像这样?
union MyUnion
{
int qty_;
double price_;
};
void someFunction()
{
MyUnion u = {0};
}
#6
-1
You'll have to wait for C++0x to be supported by compilers to get this. Until then, sorry.
您必须等待c++ 0x得到编译器的支持才能得到这个。在那之前,对不起。
#1
41
Question 1: Default constructors do initialize POD members to 0 according to the C++ standard. See the quoted text below.
问题1:默认构造函数根据c++标准将POD成员初始化为0。参见下面的引用文本。
Question 2: If a constructor must be specified in a base class, then that class cannot be part of a union.
问题2:如果一个构造函数必须在基类中指定,那么这个类就不能是联合的一部分。
Finally, you can provide a constructor for your union:
最后,您可以为您的工会提供一个构造函数:
union U
{
A a;
B b;
U() { memset( this, 0, sizeof( U ) ); }
};
For Q1:
Q1:
From C++03, 12.1 Constructors, pg 190
从c++ 03, 12.1构造函数,pg 190
The implicitly-defined default constructor performs the set of initializations of the class that would be performed by a user-written default constructor for that class with an empty mem-initializer-list (12.6.2) and an empty function body.
隐含定义的默认构造函数执行类的初始化集,该类由用户编写的默认构造函数执行,该构造函数具有一个空的mem-initializer-list(12.6.2)和一个空的函数体。
From C++03, 8.5 Initializers, pg 145
从c++ 03, 8.5初始化器,pg 145
To default-initialize an object of type T means:
默认初始化类型为T的对象意味着:
- if T is a non-POD class type (clause 9), the default constructor for T is called (and the initialization is ill-formed if T has no accessible default constructor);
- 如果T是一种非pod类类型(第9条),则调用T的默认构造函数(如果T没有可访问的默认构造函数,则初始化是病态的);
- if T is an array type, each element is default-initialized;
- 如果T是数组类型,则每个元素都是默认初始化的;
- otherwise, the object is zero-initialized.
- 否则,对象是零初始化的。
To zero-initialize an object of type T means:
零初始化类型为T的对象意味着:
- if T is a scalar type (3.9), the object is set to the value of 0 (zero) converted to T;
- 如果T是标量类型(3.9),则将对象设置为转换为T的0 (0);
- if T is a non-union class type, each non static data member and each base-class subobject is zero-initialized;
- 如果T是一个非union类类型,则每个非静态数据成员和每个base类subobject都是零初始化的;
- if T is a union type, the object’s first named data member is zero-initialized;
- 如果T是一个联合类型,则对象的第一个命名数据成员为零初始化;
- if T is an array type, each element is zero-initialized;
- 如果T是数组类型,则每个元素都是零初始化的;
- if T is a reference type, no initialization is performed.
- 如果T是引用类型,则不执行初始化。
For Q2:
Q2:
From C++03, 12.1 Constructors, pg 190
从c++ 03, 12.1构造函数,pg 190
A constructor is trivial if it is an implicitly-declared default constructor and if:
如果构造函数是隐式声明的默认构造函数,并且如果:
- its class has no virtual functions (10.3) and no virtual base classes (10.1), and
- 它的类没有虚函数(10.3),也没有虚基类(10.1),并且
- all the direct base classes of its class have trivial constructors, and
- 它的类的所有直接基类都有普通的构造函数
- for all the nonstatic data members of its class that are of class type (or array thereof), each such class has a trivial constructor
- 对于类类型(或其数组)的类的所有非静态数据成员,每个此类类都有一个普通的构造函数
From C++03, 9.5 Unions, pg 162
从c++ 03, 9.5联盟,第162页
A union can have member functions (including constructors and destructors), but not virtual (10.3) functions. A union shall not have base classes. A union shall not be used as a base class.An object of a class with a non-trivial constructor (12.1), a non-trivial copy constructor (12.8), a non-trivial destructor (12.4), or a non-trivial copy assignment operator (13.5.3, 12.8) cannot be a member of a union, nor can an array of such objects
联合可以有成员函数(包括构造函数和析构函数),但不能有虚函数(10.3)。工会不得有基类。联盟不应被用作基类。一个具有非平凡构造函数(12.1)的类的对象,一个非平凡的复制构造函数(12.8),一个非平凡的解构函数(12.4),或者一个非平凡的复制赋值运算符(13.5.3,12.8)不能是一个联合的成员,也不能是这样的对象数组。
#2
24
Things changed for the better in C++11.
在c++ 11中,情况变得更好了。
You can now legally do this, as described by Stroustrup himself (I reached that link from the Wikipedia article on C++11).
您现在可以合法地这样做,就像Stroustrup自己描述的那样(我从Wikipedia关于c++ 11的文章中找到了这个链接)。
The example on Wikipedia is as follows:
*上的例子如下:
#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 goes into a little more detail.
Stroustrup讲得更详细一些。
#3
3
AFAIK union members may not have constructors or destructors.
AFAIK联盟成员可能没有构造函数或析构函数。
Question 1: no, there's no such guarantee. Any POD-member not in the constructor's initialization list gets default-initialized, but that's with a constructor you define, and has an initializer list. If you don't define a constructor, or you define a constructor without an initializer list and empty body, POD-members will not be initialized.
问题1:不,没有这样的保证。任何不在构造函数的初始化列表中的pod成员都将被默认初始化,但这是您定义的构造函数,并具有初始化列表。如果没有定义构造函数,或者定义没有初始化器列表和空主体的构造函数,那么pod成员将不会被初始化。
Non-POD members will always be constructed via their default constructor, which if synthesized, again would not initialize POD-members. Given that union members may not have constructors, you'd pretty much be guaranteed that POD-members of structs in a union will not be initialized.
非pod成员将始终通过它们的默认构造函数来构造,如果合成了这些构造函数,也不会初始化pod成员。考虑到union成员可能没有构造函数,您将几乎得到保证,不会初始化union中结构体的POD-members。
Question 2: you can always initialize structures/unions like so:
问题2:你可以像这样初始化结构/联合:
struct foo
{
int a;
int b;
};
union bar
{
int a;
foo f;
};
bar b = { 0 };
#4
2
As mentioned in Greg Rogers' comment to unwesen's post, you can give your union a constructor (and destructor if you wish):
正如Greg Rogers对unwesen的文章所提到的那样,您可以给您的union一个构造函数(如果您希望的话,也可以是析构函数):
struct foo
{
int a;
int b;
};
union bar
{
bar() { memset(this, 0, sizeof(*this)); }
int a;
foo f;
};
#5
0
Can you do something like this?
你能做这样的事吗?
class Outer
{
public:
Outer()
{
memset(&inner_, 0, sizeof(inner_));
}
private:
union Inner
{
int qty_;
double price_;
} inner_;
};
...or maybe something like this?
…或者像这样?
union MyUnion
{
int qty_;
double price_;
};
void someFunction()
{
MyUnion u = {0};
}
#6
-1
You'll have to wait for C++0x to be supported by compilers to get this. Until then, sorry.
您必须等待c++ 0x得到编译器的支持才能得到这个。在那之前,对不起。