Understanding the structure of a class object

I am reading article 12.7 from N3797. The following example is provided:

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.yi; //3 undefined, refers to member's member A* pa = &bobj; B bobj; extern X xobj; int* p3 = &xobj.i; X xobj; 

In this example, the rule should be specified:

For an object with a non-trivial constructor, referring to any non-static member or base class of the object before the constructor starts execution of the results in undefined.

But I have one doubt. If the implementation does not perform dynamic initialization for //1 , //2 and //3 static way, we do not have undefined behavior in //2 and //3 , because (3.6.2 / 1):

Continuous initialization is performed:

[...]

- if an object with a static or storage duration of the stream is initialized by the constructor a call , and if the full initialization expression is a constant initializer for the object;

[...]

Together, zero initialization and constant initialization are called static initialization; all other initializations are dynamic initialization. Static initialization must be performed before any dynamic initialization is performed.

That is, we have what the constructor called before the non-static and basic. Thus, the result of this example is determined by the implementation.

Are my reasoning correct?

+5
source share
1 answer

"it can also call constexpr constructors", Y :: Y () is not a constexpr constructor, so B bobj gets into dynamic initialization.

0
source

Source: https://habr.com/ru/post/1201014/


All Articles