我看到的无限制工会的例子似乎总是在构建时使用新的位置.*有关C 11特性的文章在联合的构造函数中使用了new.
https://en.wikipedia.org/wiki/C%2B%2B11#Unrestricted_unions
#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.
};
是否有必要在这里使用新的位置?例如,这段代码在没有警告的情况下使用gcc进行编译,而valgrind在使用union来保存字符串时没有显示内存泄漏:
struct HasUnresUnion
{
enum { Int, String } tag;
HasUnresUnion(int i)
: tag(Int),
as_int(i)
{}
HasUnresUnion(std::string str)
: tag(String),
as_str(std::move(str))
{}
~HasUnresUnion()
{
using std::string;
if (tag == String)
as_str.~string();
}
union
{
int as_int;
std::string as_str;
};
};
这似乎没有任何歧义,所以我不明白为什么标准会取缔这个.这是合法代码吗?当联合未初始化(而不是被分配)时,是否需要新的位置?是否需要联盟中的构造函数?我确实看到没有自己的构造函数的无限制工会,但*明确表示它是必需的.
解决方法:
介绍
你展示的片段非常安全;在初始化类似联合的类时,法律允许您初始化一个非静态数据成员.
例
*文章中有一个示例,其中使用了placement-new,因为它们在可以直接初始化某个成员的点之后写入成员.
union A {
A () { new (&s1) std::string ("hello world"); }
~A () { s1.~basic_string<char> (); }
int n1;
std::string s1;
};
然而,前面的代码段在语义上等同于以下内容,其中我们明确声明在构造A时应初始化A :: s1.
union A {
A () : s1 ("hello world") { }
~A () { s1.~basic_string<char> (); }
int n1;
std::string s1;
};
精
在你的代码片段中,你的类中有一个匿名联合(这使你的类成为一个类似联合的类),这意味着除非你在类的初始化期间初始化union的一个成员 – 你必须使用placement-new来初始化他们以后再来.
标准说什么?
06002
In a union, at most one of the non-static data members can be active at any
time, that is, the value of at most one of the non-static data members can
be stored in a union at any time.06003
[…]
The lifetime of an object of type
T
begins when:
- storage with the proper alignment and size for type
T
is obtained, and- if the object has non-trivial initialization, its initialization is complete.
The lifetime of an object of type
T
ends when:
- if
T
is a class type with a non-trivial destructor (12.4), the destructor call starts, or- the storage which the object occupies is reused or released.