理解类对象构造

5 c++ constructor

我正在阅读N3797第12.7条.给出以下示例:

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;
Run Code Online (Sandbox Code Playgroud)

此示例必须反映规则:

对于具有非平凡构造函数的对象,在构造函数开始执行之前引用对象的任何非静态成员或基类会导致未定义的行为.

但我有一个疑问.如果实现不适合进行动态初始化//1,//2以及//3以静态方式,我们没有未定义的行为在//2//3,因为(3.6.2/1):

执行常量初始化:

[...]

- 如果具有静态或线程存储持续时间的对象由构造函数 调用初始化,并且初始化full-expression是对象的常量初始化器;

[...]

零初始化和常量初始化一起称为静态初始化; 所有其他初始化是动态初始化.在进行任何动态初始化之前,应执行静态初始化.

也就是说,我们已经在非静态和基础之前调用了构造函数.因此该示例的结果是实现定义的.

我的推理是否正确?

小智 0

“它也可能调用 constexpr 构造函数”,Y::Y() 不是 constexpr 构造函数,因此 B bobj 属于动态初始化。