1

In c++11, Union supports non-POD member. I want to initialize a non-POD member in the constructor.

On wikipedia c++11 page, it uses a placement 'new' to initialize a non-POD member.

#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.
};

I am wondering is there any difference if I use ctor-initializer-list instead of placement 'new'?

U() : p() {}
timrau
  • 22,578
  • 4
  • 51
  • 64

2 Answers2

1

No, no difference for you. Just use U() : p() {}.

[ Note: In general, one must use explicit destructor calls and placement new operators to change the active member of a union. — end note ]

[ 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 ]

I.e. your first variant is correct.


The standard also says:

At most one non-static data member of a union may have a brace-or-equal-initializer.

Personally, I would expect the following to be correct:

union U {
    int z;
    double w;
    Point p {1,2};
};

#include <iostream>
int main () {
    U u;
    std::cout << u.p.x_ << ":" << u.p.y_ << std::endl;
}

I would expect the output 1:2, but with g++ 4.8.1 I get garbage values. When I try

union U {
    int z;
    double w;
    Point p = Point(1,2);
};

I get garbage values, too. I am not sure if this is a compiler bug.

edit: brace-or-equal-Initializer in unions

Community
  • 1
  • 1
Sebastian Mach
  • 38,570
  • 8
  • 95
  • 130
1

You are free to initialize at most one member of a union in the ctor-initializer-list. A union is a class, so the rules for member initializers in [class.base.init] (C++11 §12.6.2) apply just as they do to classes with the class-key struct or class. One obvious exception is stated in 12.6.2/8: "An attempt to initialize more than one non-static data member of a union renders the program ill-formed."

Casey
  • 41,449
  • 7
  • 95
  • 125