Search code examples
c++unique-ptr

Passing the object in a unique pointer as a reference to the other objects' constructor


I am using a 3rd party library, which returns a newly created object as a raw pointer. I store it in a unique_ptr with a custom destructor to properly destroy the object by calling the library's custom destructor. However, this object will be used by the other objects owned by the same parent class. I wonder if it's an acceptable design to pass the third party object as a reference into the other objects. As they have the same parent, the life time of the 3rd party object can be beyond the other objects as long as it's declared before the other objects that will keep it as a reference. Is there any concerns in this idea, or a better approach? Here is an example:

class ChildClass
{
public:
    ChildClass (ThirdPartyClass& third) : thridparty (third)
    {
    // do sth...
    }
private:
    ThirdPartyClass& thirdparty;
};

class ParentClass
{
public:
void addChild()
{
    children.emplace_back (*thirdParty);
}

private:
std::unique_ptr<ThirdPartyClass> thirdParty;
std::vector<ChildClass> children;
};

Solution

  • the life time of the 3rd party object can be beyond the other objects as long as it's declared before the other objects that will keep it as a reference

    Yes, class member fields are constructed in the order they are declared in the class body, and destroyed in the opposite order.

    For both user-defined or implicitly-defined destructors, after executing the body of the destructor and destroying any automatic objects allocated within the body, the compiler calls the destructors for all non-static non-variant data members of the class, in reverse order of declaration, then it calls the destructors of all direct non-virtual base classes in reverse order of construction (which in turn call the destructors of their members and their base classes, etc), and then, if this object is of most-derived class, it calls the destructors of all virtual bases.

    So, your design is valid and in some circumstances (e.g. you always want to pass a valid object, not nullptr to ChildClass) recommended.

    However, make sure that your std::unique_ptr<3rdPartyClass> thirdParty; points to the object returned by your 3rd party library ASAP, preferably in ParentClass constructor. Otherwise you can't safely call addChild because you risk nullptr dereference, which is UB.

    Also:

    • 3rdPartyClass is not a valid C++ id
    • it's just enough to ChildClass(*thirdParty)