79799374

Date: 2025-10-25 07:36:52
Score: 0.5
Natty:
Report link

You can wrap the member in a union.

#include <iostream>
using std::cout;
struct A {
  A() { cout << "A's constructor was called!\n"; }
};

struct B {
  union { A member; };
  B() {
    cout << "B's constructor was called!\n";
  }
};

int main() {
  B b; // will only print "B's constructor was called!"
}

member will not have its constructor or destructor called.

How to have more members, of possibly other types?

If you want to have multiple members be uninitialized, create a separate union for each of them. So for example if you wanted B to hold additional members of any types C, D, E , you'd declare it as such:

struct B {
  union { A a; };
  union { C c; };
  union { D d; };
  union { E e; };
  // ... and so on
  B() { cout << "B's constructor was called!\n"; }
};

It's also ok to have multiple members of the same type, just make sure each member is in its own union:

struct B {
  union { A x; };
  union { A y; };
  union { A z; };
  // ... and so on
  B() { cout << "B's constructor was called!\n"; }
};

How to initialize the members?

Whenever you want to manually initialize any members declared like this, you may do so using the placement-new syntax. The placement-new syntax looks like this: new (&variable) Type(arguments to the constructor); This might look a little weird so I will show an example below.

Going back to the simple case, here's an example where B has a method initializeA to initialize member, using the placement-new syntax.

#include <iostream>
using std::cout;
struct A {
  A() { cout << "A's constructor was called!\n"; }
};

struct B {
  union { A member; };
  B() {
    cout << "B's constructor was called!\n";
  }
  void initializeA() {
    new (&member) A();
  }
};

int main() {
  B b; // will only print "B's constructor was called!"
  b.initializeA(); // will print "A's constructor was called!"
}

The placement-new syntax allows you to pass arguments to the constructor.

How to destroy members?

Finally if you have initialized some member, it's important to remember that you have to do the work of calling the destructor yourself!

Here's an example where B calls the destructor of A to destroy it.

#include <iostream>
using std::cout;
struct A {
  A() { cout << "A's constructor was called!\n"; }
  A() { cout << "A's destructor was called!\n"; }
};

struct B {
  union { A member; };
  B() {
    cout << "B's constructor was called!\n";
  }
  void initializeA() {
    new (&member) A();
  }
  void destroyA() {
    A::~A();
  }
};

int main() {
  B b; // will only print "B's constructor was called!"
  b.initializeA(); // will print "A's constructor was called!"
}

But this is a little error-prone since you should only call the destructor of A if you have already initialized A. Perhaps B would have a variable to keep track of this, making it a little safer. And put it in the destructor of B so that we won't forget.

#include <iostream>
using std::cout;
struct A {
  A() { cout << "A's constructor was called!\n"; }
  ~A() { cout << "A's destructor was called!\n"; }
};

struct B {
  union { A member; };
  bool initialized;
  B(): initialized(false) {
    cout << "B's constructor was called!\n";
  }
  void initializeA() {
    // constructor should only be called if A is uninitialized
    if (!initialized) {
      new (&member) A();
      initialized = true;
    }
  }
  void destroyA() {
    // the destructor should only be called if A is *initialized*
    if (initialized) {
      A::~A();
      initialized = false;
    }
  }
  ~B() {
    destroyA();
  }
};

int main() {
  B b; // will only print "B's constructor was called!"
  b.initializeA(); // will print "A's constructor was called!"
} // will print "A's destructor was called!" in B's destructor

I hope this was helpful. It's interesting how much you can do with the control C++ gives you over things like this.

Reasons:
  • Long answer (-1):
  • Has code block (-0.5):
  • Contains question mark (0.5):
  • Unregistered user (0.5):
  • Low reputation (1):
Posted by: eiplusplus