I have a class that up until this point had a reference to another class because it didn't own that class and was not responsible for managing it's memory.
class MyClass
{
OtherClass& m_other;
public:
MyClass( OtherClass& other ) : m_other( other ) {}
};
I am however in a situation where in some cases MyClass is the owner of m_other and I'd like a deletion to lead to the deletion OtherClass. And in some cases it isn't the owner.
In this instance, is it more appropriate to have two classes to represent both cases or to have a single class that encapsulates both cases (with a unique_ptr). e.g.
class MyClassRef
{
OtherClass& m_other;
public
MyClassRef( OtherClass& other ) : m_other( other ) {}
};
class MyClassOwner
{
std::unique_ptr<OtherClass> m_other; // Never null
public:
MyClassOwner( std::unique_ptr<OtherClass> other ) : m_other( std::move( other ) ) {}
};
vs
class MyClass
{
OtherClass& m_other; // class may or may not be the one we manage.
std::unique_ptr<OtherClass> m_managed; // May be null
public:
MyClass( std::unique_ptr<OtherClass> managed ) : m_other( *managed ), m_managed( std::move( m_managed ) ) {}
MyClass( OtherClass& other ) : m_other( other ), m_managed() {}
};
This is probably a rather simple example, but in general when dealing with split cases is it better to create new classes to handle these cases... or to encapsulate as many cases in a single class - to a reasonable level.
Edit: A third option which is similar to the second option is to use std::shared_ptr<T> e.g.
class MyClass
{
std::shared_ptr<OtherClass> m_other;
public:
MyClass( std::shared_ptr<OtherClass> other) : m_other( other ) {}
MyClass( OtherClass& other ) : m_other( std::shared_ptr<OtherClass>( &other, []( OtherClass* p ){} ) ) {}
};
Note that I want MyClass to still accept references as to allow pointers to stack-allocated objects; this is why the constructor creates a shared_ptr<OtherClass> with a custom deleter not to delete the stack object.
When the class may be an owner in some cases, while in some other cases it is not an owner, you should use std::shared_ptr<T>, which maintains use count, in place of std::unique_ptr<T>, which requires unique ownership of the resource.
As long as all references to the object pointed to by m_other are maintained through std::shared_ptr<T> smart pointers, resource management would be automated for you, regardless of the part of the program that owns the object.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With