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.)