问题
I'm reading clause 12.7 of N3797. The following example is given:
struct X { int i; };
struct Y : X { Y(); }; // non-trivial
struct A { int a; };
struct B : public A { int j; Y y; }; // non-trivial
extern B bobj;
B* pb = &bobj; //1
int* p1 = &bobj.a; //2 undefined, refers to base class member
int* p2 = &bobj.y.i; //3 undefined, refers to member’s member
A* pa = &bobj;
B bobj;
extern X xobj;
int* p3 = &xobj.i;
X xobj;
This example must reflect the rule:
For an object with a non-trivial constructor, referring to any non-static member or base class of the object before the constructor begins execution results in undefined behavior.
But I've one doubt. If an implementation doesn't perform dynamic initialization for //1, //2, and //3 in a static way, we have no undefined behavior at //2 and //3, because (3.6.2/1):
Constant initialization is performed:
[...]
— if an object with static or thread storage duration is initialized by a constructor call, and if the initialization full-expression is a constant initializer for the object;
[...]
Together, zero-initialization and constant initialization are called static initialization; all other initialization is dynamic initialization. Static initialization shall be performed before any dynamic initialization takes place.
That is, we have that constructor has called before a non-static and base. So the result of that example is implementation defined.
Is my reasoning correct?
回答1:
"it may also invoke constexpr constructors", Y::Y() is not constexpr constructor so B bobj falls to dynamic initialization.
来源:https://stackoverflow.com/questions/25470791/understanding-class-object-construction