简体   繁体   中英

initialization of class member in anonymous union

I have observed that the following code segfaults at the line ar.p() :

#include <iostream>

class A
{
public:
  virtual void p() { std::cout<<"A!\n"; }
};

class B : public A
{
public:
  void p() { std::cout<<"B!\n"; }
};

struct Param
{
  enum {AA, BB} tag;
  union {
    A a;
    B b;
  };

  Param(const A &p)
    : tag(AA) {a = p;}

  A &get() {
    switch(tag) {
    case AA: return a;
    case BB: return b;
    }
  }
};

int main() {
  A a;
  a.p();
  Param u(a);
  A &ar = u.get();
  ar.p();
}

However, when I change the Param constructor to:

Param(const A &p)
  : tag(AA), a(p) {}

it does not segfault anymore.

I think it has something to do with the way the vtable ptr for union member a is initialized, but I'd like to understand this bug better.

On coliru: http://coliru.stacked-crooked.com/a/85182239c9f033c1

The union doesn't have an implicit constructor, you have to add your own constructor to the union which initializes one of the members of the union. I think this is because the compiler can't know whether you want to initialize a or b . You may also need an assignment operator and destructor. See also this question: Why does union has deleted default constructor if one of its member doesn't have one whatsoever?

The constructor should use placement new or it can use a member initializer to construct one of the union members, as you do in your alternative constructor.

If you want to assign something to b afterwards, you have to destruct a using a.~A() , and then initialize b with placement new.

If you have members in the union with a non-trivial destructor then the union must have a destructor which calls the destructor on the member which is used at that point.

In your original code the assignment operator and the p() method are called without running a constructor first, leading to the crash.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM