views:

439

answers:

1

The question I have are NOT homework questions, but I am considering using these concepts in my assignment. The content,if it helps, is like this: I need to keep track of several union instances and they belong to my own union in one of my own class as class variables. (Note: the number of union instance is unknown, so I cannot just have a fixed number of union instances.

  1. Q1: If I have a union say MyUnion, and many instances of this union, can I then put them into a vector like

    vector<union MyUnion> myVector(10);
    
  2. Q2: Is it valid to have a pointer of union? like

    union MyUnion *myUnionPtr = new union myUnion;
    
  3. Q3: I am considering using a vector of union pointers in my implementation, is this concept correct? Also, is it a normal approach in c++? Do I need to rethink about my design?

thank you

+12  A: 
  1. If the union is CopyConstructable and Assignable, then it meets the requirements for std::vector.
  2. Yes: MyUnion* ptr = new MyUnion();
  3. A container of pointers works in some situations, but if you want a container of owning pointers, look at Boost's ptr_* containers. However, here it appears you'd either have a container of non-pointers or a container of non-owning pointers, either of which is fine and common for vector.


All types are, by default, both CopyConstructable and Assignable. ("Copyable" is used to mean the union of these concepts, however the standard specifies them individually.) This is because copy ctors and op= are added to classes (unions are one class-type) except under certain circumstances. There are a few references online, but I'm not aware of a single one, available freely online, that spells these out.

You have to go out of your way to prevent it, such as:

  • make the copy ctor or op= non-public
  • make the copy ctor or op= take a non-const reference
  • give the class type a non-CopyConstructable or non-Assignable member

Example:

union CopyableUnion {
  int n;
  char c;
  double d;
};

union NonCopyableUnion {
  int n;
  char c;
  double d;

  NonCopyableUnion() {} // required, because any user-defined ctor,
  // such as the private copy ctor below, prevents the supplied
  // default ctor

private:
  NonCopyableUnion(NonCopyableUnion const&);
  NonCopyableUnion& operator=(NonCopyableUnion const&);
};

int main() {
  CopyableUnion a;
  CopyableUnion b = a; // fine, uses copy ctor
  b = a; // fine, uses op=

  NonCopyableUnion c;
  NonCopyableUnion d = c; // compile error (copy ctor)
  d = c; // compile error (op=)

  return 0;
}


Note: And just because something is Copyable, doesn't mean it does what you want! Example:

struct A {
  int* p;

  A() : p(new int()) {}

  // the provided copy ctor does this:
  //A(A const& other) : p(other.p) {}
  // which is known as "member-wise" copying

  ~A() { delete p; }
};

int main() {
  A a;
  {
    A b = a;
    assert(b.p == a.p); // this is a problem!
  } // because when 'b' is destroyed, it deletes the same pointer
  // as 'a' holds

  return 0; // and now you have Undefined Behavior when
  // ~A tries to delete it again
}

The same thing holds true for unions, of course. The fix applies equally, though, as well:

struct A {
  int* p;

  A() : p(new int()) {}

  A(A const& other) : p(new int(*other.p)) {}

  ~A() { delete p; }
};

(If you spotted it, yes, A has a problem if you ever try to use op=, in just the same way as it originally had with the copy ctor.)

Roger Pate
how can I determine if a union is CopyConstructable and Assignable?
derrdji
@derrdji: I think as long as all of the members are (don't explicitly deny it) and the union itself doesn't explicitly deny it.
Sydius