初始化时将子类结构体成员地址传给父类是否安全?
Great question! Let's break down whether this code is safe and why.
First, let's recap your code for clarity:
struct Foo { int a; int b; }; class A { public: A(void* fooHandle) : _fooHandle(fooHandle) {} private: void* _fooHandle; }; class B : public A { public: B() : A(&_foo) { /* _foo initialized here */ } private: Foo _foo; };
Key Background: C++ Object Construction Order
To understand why this works (or where the pitfalls are), we need to remember the strict order of operations when creating a B object:
- The compiler allocates memory for the entire
Binstance first. This includes all members of the base classA, plusB's private_foomember—so_foohas a fixed memory location from the start. - Next, the base class
A's constructor is called (this is why yourA(&_foo)runs before anything else inB's initialization). - After
Ais fully constructed,B's member variables (in this case,_foo) are initialized (for POD types likeFoo, this means raw memory is ready; for non-POD types, their constructors run here). - Finally,
B's constructor body executes.
Is &_foo a valid address in A's constructor?
Yes! Even though _foo hasn't been initialized yet, its memory location is already allocated as part of the B object. Taking its address is a safe, well-defined operation—you won't get a null pointer or garbage address here.
The Critical Caveat
While the address itself is valid, you cannot safely access the contents of _foo from within A's constructor. At that point:
- For POD types like
Foo, theaandbmembers are uninitialized (their values are garbage). - For non-POD types, the object's constructor hasn't run yet, so the object is in an invalid state.
If A's constructor only stores the address (like your code does) and doesn't try to dereference it or access any members, your code is completely safe. The address can be used later (e.g., in member functions called after B is fully constructed) without issue.
Summary
Your implementation is safe, as long as you follow this rule: never dereference the _fooHandle pointer in A's constructor or any code that runs before B's _foo member is fully initialized.
内容的提问来源于stack exchange,提问作者Lukas Kalinski

