I have:
class Foo;
class Bar {
Foo foo;
Bar(): foo(foo) {};
}
Bar bar;
At this point, is
bar.foo // <--- how is this initialized?
[This question arose from a buggy ref-counted pointer implemntation; I could have sworn that I ensured each pointer was pointing at something non-null; but I ended up with a pointer that pointed at something NULL.]
foo
is fully initialized once you've entered the body of the constructor (that's the guaranteed general case; specifically once it has finished initializing in the initialize list.)
In your case, you are copy-constructing from a non-constructed object. This results in undefined behavior, per §12.7/1 (thank you, gf):
For an object of non-POD class type (clause 9), before the constructor begins execution and after the destructor finishes execution, referring to any nonstatic member or base class of the object results in undefined behavior.
In fact, it gives this example:
struct W { int j; };
struct X : public virtual W { };
struct Y {
int *p;
X x;
Y() : p(&x.j) // undefined, x is not yet constructed
{ }
};
Note, the compiler is not required to give a diagnosis of undefined behavior, per §1.4/1. While I think we all agree it would be nice, it simply isn't something the compiler implementers need to worry about.
Charles points out a loophole of sorts. If Bar
has static storage and if Foo
is a POD type, then it will be initialized when this code runs. Static-stored variables are zero-initialized before an other initialization runs.
This means whatever Foo
is, as long as it doesn't need a constructor to be run to be initialized (i.e., be POD) it's members will be zero-initialized. Essentially, you'll be copying a zero-initialized object.
In general though, such code is to be avoided. :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With