The examples I've seen of unrestricted unions always seem to use placement new when constructing. The Wikipedia article for C++11 features uses placement new in the constructor of a union.
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.
};
Is it necessary to use placement new here? For example, this piece of code compiles without warnings with gcc and valgrind shows no memory leaks when the union is used to hold a string:
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;
};
};
It doesn't seem like there's any ambiguity here so I don't see why the standard would outlaw this. Is this legal code? Is placement new necessary when the union is uninitialized (rather than being assigned to)? Is the constructor in the union required? I've definitely seen unrestricted unions without their own constructors but Wikipedia explicitly states it's required.
See Question&Answers more detail:
os 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…