Creating an x::ref or an x::ptr from this

An x::ref or an x::ptr can be constructed from a native object pointer. This is frequently used by class methods to create pointers or references to the this object:

class widgetObj : virtual public x::obj {

// ...


typedef x::ref<widgetObj> widget;

// ...

void widgetObj::method()
    // ...

    widget myRef(this);

    // ...

This allows a class method to create an x::ref or an x::ptr to the object pointed by this, so that it can be passed along to other objects or methods, for example. Note, however:


Creating an x::ref or an x::ptr to this in the object's constructor is generally prohibited, for the following reason. The object has not finished its own construction, but the x::obj virtual superclass is already constructed, with its reference count set to zero. What normally happens when the object gets fully constructed is that it gets assigned to its initial x::ref or an x::ptr, which increments the reference count to 1, resulting in an object with a single reference. But this hasn't happened yet. The object is still in its constructor.

If the object's constructor also creates an x::ref or an x::ptr from this, the object's reference count gets incremented to 1 prematurely. This is no different than from any other x::ref or an x::ptr getting created from this. But now, if the x::ref or an x::ptr that was created from this goes out of scope and gets destroyed before the original constructor finishes, the object's count becomes zero again. When that happens, the object gets destroyed.

But, if you're keeping score, the initial constructor hasn't returned yet. When the constructor returns, the newly-created object is already destroyed. However, the object has been created in the context of initializing the first reference to the object, so the caller's context expects the constructor to produce a new object, whose reference count gets immediately incremented. Memory corruption results.

Furthermore, creating an x::ref or an x::ptr from this in its own destructor is also a non-starter.