The point is in the constructor _A. As the cppreference says:
The default constructor for the class T is trivial (i.e. does not perform any actions) if all of the following is true:
- The constructor is not provided by the user (i.e. implicitly set or default)
- T has no virtual member functions
- T does not have virtual base classes
- T has no non-static elements with logical or equal initializers. (since C ++ 11)
- Each direct base T has a trivial default constructor
- Each non-static member of a class type has a trivial default constructor.
This one is not trivially constructive
class _A{ public: _A(){} };
bye this
class _A{ public: };
and in the case of an example, this definitely does not have a trivial constructor:
class _A{ public: _A(){} C<_B> g; };
this means that the constructor performs initialization procedures for members of the class. As stated in standard 14.7.1 [temp.inst]
initialization (and any side effects associated with it) of a static data member does not occur if the static data member itself is not used in such a way that a static data element definition is required
and since the non-trivial constructor simply provided us with the use (and not the need ) for initializing static variables, CRT starts its work and starts initializing
const static C<T> nullObj;
which, in turn, shares something unified, and you have undefined behavior.
To decide, as indicated in the quantum code, either initialize B<_B>::nullObj before this process, or change the design of your code.
source share