What are Unrestricted Unions proposed in C++11?

2019-01-22 14:13发布

问题:

I gather unrestricted unions as one of the functionality being put forth in C++11. Can anyone please explain the semantics behind this and the advantages it provides?

回答1:

There is an explaination on Wikipedia : http://en.wikipedia.org/wiki/C%2B%2B0x#Unrestricted_unions

Search there first before asking about C++0x features explainations.

Unrestricted unions

In Standard C++ there are restrictions on what types of objects can be members of a union. For example, unions cannot contain any objects that define a non-trivial constructor. C++0x will alleviate some of these restrictions, allowing unions to be used on more types that they were previously not allowed to be used on.[6] This is a simple example of a union permitted in C++0x:

//for placement new
#include <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++; point has a non-trivial constructor. 
              //   However, this is legal in C++0x.
    U() { new( &p ) Point(); } // No nontrivial member functions are
                               //implicitly defined for a union;
                               // if required they are instead deleted
                               // to force a manual definition.
};

The changes will not break any existing code since they only relax current rules.



回答2:

It is nothing else than the old unions we have always had, an object containing one member at a time, of varying type.

The change is just that you are now allowed to store non-POD types in a union. However, you will then be responsible for explicitly constructing and destroying that member.

From N3242:

[ Example: Consider an object u of a union type U having non-static data members m of type M and n of type N. If M has a non-trivial destructor and N has a non-trivial constructor (for instance, if they declare or inherit virtual functions), the active member of u can be safely switched from m to n using the destructor and placement new operator as follows:
u.m.~M();
new (&u.n) N;
—end example ]

Not a widely useful feature, IMO.



回答3:

It expands unions to allow any type, not just "plain old data", giving you more flexibility to store different types of data in the same location without resorting to manual pointer hackery.

The price you pay for this is that you have to do some careful book keeping. With a plain old data union assignment was enough to change the "current type" and reading the wrong type was likely to result in garbeledled data but not much more than that. With a non plain old data uninion you must keep track of the current type and call the corect constructors and destructors manually to change the current type and to clean things up correctly when destroying the union as a whole. If you try to read or write the wring type bad things are likely to happen



标签: c++ c++11 unions