Consider the following example. When bar is constructed, it gives it\'s base type (foo) constructor the address of my_member.y where <
First let's make accurate the question.
What you are doing isn't using an uninitialized object, you are using an object not within its lifetime. my_member is constructed after foo, therefore the lifetime of my_member hasn't begun in foo(&my_member.y).
From [basic.life]
before the lifetime of an object has started but after the storage which the object will occupy has been allocated [...], any glvalue that refers to the original object may be used but only in limited ways. [...] such a glvalue refers to allocated storage, and using the properties of the glvalue that do not depend on its value is well-defined. The program has undefined behavior if:
- the glvalue is used to access the object, or [...]
Here accessing it means specifically to either read or modify the value of the object.
The evaluation of my_member yields a lvalue, and there is nothing necessitating a conversion to prvalue, hence it stays a lvalue. Likewise, the evaluation of my_member.y is also a lvalue. We then conclude that no object's value have been accessed, this is well-defined.
Yes you are allowed to pass &my_member.y to foo's constructor, and even copy the pointer - which you do with x(p_x).
The behaviour on dereferencing that pointer though in foo's constructor is undefined. (But you don't do that.)