c++ - Unrestricted union in practice -
i have questions unrestricted unions , application in practice. let's suppose have following code :
struct mystruct { mystruct(const std::vector<int>& a) : array(a), type(array) {} mystruct(bool b) : boolean(b), type(bool) {} mystruct(const mystruct& ms) : type(ms.type) { if (type == array) new (&array) std::vector<int>(ms.array); else boolean = ms.boolean; } mystruct& operator=(const mystruct& ms) { if (&ms != this) { if (type == array) array.~vector<int>(); // edit(2) if (ms.type == array) new (&array) std::vector<int>(ms.array); else boolean = ms.boolean; type = ms.type; } return *this; } ~mystruct() { if (type == array) array.~vector<int>(); } union { std::vector<int> array; bool boolean; }; enum {array, bool} type; };
- is code valid :) ?
- is necessary explicitly call vector destructor each time using boolean (as stated here http://cpp11standard.blogspot.com/2012/11/c11-standard-explained-1-unrestricted.html)
- why placement new required instead of doing 'array = ms.array' ?
edit:
- yes, compiles
- "members declared inside anonymous unions members of containing class, , can initialized in containing class's constructor." (c++11 anonymous union non-trivial members)
- adding explicit destructors suggested, leads sigsev g++ 4.8 / clang 4.2
- the code's buggy: change
array.clear();
array.~vector<int>();
explanation: operator=
using placement new
on object hasn't been destructed, practically can expect leak dynamic memory previous array had been using (clear()
doesn't release memory / change capacity, destructs elements , changes size
).
from 9.5/2:
if non-static data member of union has non-trivial default constructor (12.1), copy constructor (12.8), move constructor (12.8), copy assignment operator (12.8), move assignment operator (12.8), or destructor (12.4), corresponding member function of union must user-provided or implicitly deleted (8.4.3) union.
so, vector
constructor, destructor etc never kicks in themselves: must call them explicitly when wanted.
in 9.5/3 there's example:
consider following union:
union u { int i; float f; std::string s; };
since std::string (21.3) declares non-trivial versions of of special member functions, u have implicitly deleted default constructor, copy/move constructor, copy/move assignment operator, , destructor. use u, or of these member functions must user-provided.
that last bit - "to use u, or of these member functions must user-provided." - seems presume u
needs coordinate own vaguely value-semantic behaviour, in case surrouding struct
doing don't need define of these union
member functions.
2: must call array destructor whenever array value being replaced boolean value. if in operator=
new array value being placement-new
ed instead of assigned, old array must have destructor called, using operator=
more efficient when existing memory sufficient elements being copied. basically, must match constructions , destructions. update: example code has bug per comment below.
3: why placement new required instead of doing 'array = ms.array' ?
array = ms.array invokes std::vector<int>::operator=
assumes this
pointer addresses constructed object. inside object can expect there pointer either null or refer internal short-string buffer, or refer heap. if object hasn't been destructed, operator=
may call memory deallocation function on bogus pointer. placement new says "ignore current content of memory object occupy, , construct new object valid members scratch.
Comments
Post a Comment