'Initialization of a base class reference from a derived class member

I have two classes, Base and Derived. Derived constructs Base using its own member object, which inherits from Base::BaseChild.

struct Base
{
    struct BaseChild
    {
        int x = 5;
    };
    Base(BaseChild& c): baseData(c), constantVar(c.x) 
    {
       assert(constantVar == 5);
    }
    int getX() const {return baseData.x;}

private:
    const int constantVar;
    BaseChild& baseData;
};


struct Derived: public Base
{
    struct DerivedChild: public BaseChild
    {
        double y = 4.0;
    };
    Derived(): Base(data) {}

private:
    DerivedChild data;
};


Derived myObject;
assert(myObject.getX() == 5);

Reasoning: I do this in this way because everything seems pretty encapsulated for my case, where I need to send Childs to swap their content (vector, shared_ptr, unique_ptr) with other Childs, keeping child memory address, and I still can access to Child object from base class without the need of a virtual function, which was killing my app performance.

Question: I've read another post like this one, where it states initialization of a Derived member before the Base isn't possible. So the constantVar assert would always fail. However getX() works fine, after the constructor, and I'm interested in these functions which are called once the constructor ends. Is this safe? Or is there any hidden danger here?



Solution 1:[1]

The base class Base of Derived is constructed before the member data.

As a result data will not be initialized when you pass a reference to it to Base's constructor. The initialization will happen after that constructor call.

You are however trying to read the member x of data in Base's constructor. At this point data's lifetime has not started yet and accessing the value of a non-static data member of an object outside its lifetime causes undefined behavior.

Whether or not the assertions succeed isn't significant. Undefined behavior allows for either outcome.

The situation would be potentially different (although technically not rules in the standard) if you were not trying to access the value of data inside Base's constructor, but only storing the reference to it.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1