flamasterrr
flamasterrr

Reputation: 315

Specific case of dangling reference during destruction

This is the code I cannot change and have to adapt to:

struct SomeInterface
{
   ...
};

struct SomeClass
{
   SomeClass(SomeInterface& iface) : iface(iface) {}
   SomeInterface& iface;
   ...
};

I have to write a function where I will get SomeInterface from other function and return pointer to SomeClass which takes a reference to SomeInterface. The problem was, unique_ptr to SomeInterface will be created on that function stack so reference is gonna be invalid after returning from it. I wrote a simple wrapper class which inherits from SomeClass and extends it to hold a unique_ptr to SomeInterface.

std::unique_ptr<SomeClass> getSomeClass()
{
   struct SomeClassWrapper : public SomeClass
   {
      SomeClassWrapper(std::unique_ptr<SomeInterface> iface) 
        : SomeClass(*iface), 
          iface(std::move(iface)) {}

      std::unique_ptr<SomeInterface> iface;
   };

   std::unique_ptr<SomeInterface> iface = getIfaceFromSomewhere();

   return std::unique_ptr<SomeClass>(std::make_unique<SomeClassWrapper>(std::move(iface))
}

This solves SomeInterface's lifetime problem... almost. Unfortunately during destruction of SomeClassWrapper the member variable iface is destroyed first, so for a brief moment base class SomeClass holds a dangling reference.

How to achieve my desired result without this problem?

Cheers

Upvotes: 0

Views: 45

Answers (1)

walnut
walnut

Reputation: 22152

Move the unique_ptr into a base class that is constructed first and destructed last:

struct SomeClassWrapperPtrMember {
    std::unique_ptr<SomeInterface> iface;
};

struct SomeClassWrapper : public SomeClassWrapperPtrMember, SomeClass
{
     SomeClassWrapper(std::unique_ptr<SomeInterface> iface) 
        : SomeClassWrapperPtrMember{std::move(iface)},
          SomeClass(*(this->iface)) {}
};

Upvotes: 1

Related Questions