Tejendra
Tejendra

Reputation: 1934

How to use same unique_ptr in multiple classes

I am trying to change my current design and want to use smart pointers (preferably unique_ptras Herb Sutter says, when in doubt, prefer unique_ptr by default) but I am confused which fits in my current design where one pointer will be passed to multiple classes.

The sample code is as follows

class X {
private:
    ZHandler* _mZHandler; //change it as unique_ptr or shared_ptr??
public:
    X()
    {
        Z* zPtr = createUsingFactory(); // instantiated by legacy code factory function, createUsingFactory() is just representational
        _mZHandler = new ZHandler(zPtr);
    }
    ~X()
    {
        delete _mZHandler;
    }
    void callYfunc()
    {
        _mZHandler->funcY();
    }
};

//ZHandler wraps the calls to Z as well as serves as event listner to Z
class ZHandler : public Z::ZEventListner {
private:
    Z* _mPtrZ; 
public:
    ZHandler(Z* ptr) : _mPtrZ(ptr){}
    void funcY()
    {
        _mPtrZ->funcZ();
    }
    void funcNotifyEvent
    {
    }
};

class Z {
private:
    ZEventListner* _mZEventListner;
public:
    class ZEventListner{
        vitual void funcNotifyEvent() = 0;
    };
    void setEventListner(ZEventListner* ptr)
    {
        _mZEventListner = ptr;
    }
    ZEventListner* getEventListner(){return _mZEventListner};
    void funcZ(){}
    void funcNotify() //called by some other class
    {
        _mZEventListner->funcNotifyEvent();
    }
};

The question is whether to use unique_ptr or shared_ptr for ZHandler pointer in class X? (accordingly the functions and pointers will change in other classes), If i use unique_ptr then I have to move the ptr of ZHandler in setEventListner function, and once i do that the original pointer will be lost and further calls to ZHandler from X won't be possible.

Upvotes: 0

Views: 2785

Answers (2)

Galik
Galik

Reputation: 48615

Smart pointers are all about ownership. That means which objects are responsible for deleting their members. So you should look at which objects delete the things they have pointers to.

If the design is such that it is impossible to know which pointer will be the last to reference an object (and hence be the one used to delete it) then you should use a std::shared_ptr.

If, on the other hand, there is only one pointer that will outlast all other references and that will always need to be the one the object is deleted through, then that should be a std::unique_ptr.

Most owning pointers (pointers that need to delete stuff) tend to be std::unique_ptr.

If you have a pointer to an object that will always outlive the pointer and be deleted by some other object, then you should use a raw pointer or preferably a reference.

So you have to decide which objects in your design will live the longest and which objects will be responsible for destroying the objects they point to and choose your pointers accordingly.

Shared pointer: When you do not know which pointer will have to delete the object because you do not know which pointer will go out of scope (or be deleted) last.

Unique pointer: When the pointed to object will be destroyed from exactly one place and all other referees to that object will have expired before this pointer needs to delete it.

Raw pointer/Reference: When someone else is responsible for deleting the object because this pointer/reference's need to access the object will have expired before that happens.

Upvotes: 3

0kcats
0kcats

Reputation: 743

This is not a direct answer to the question, but rather an approach to avoid being confused with the smart pointers. At first, don't use either unique_ptr or shared_ptr. Instead spend a day to learn about RAII and try implementing your own "unique_ptr" (you can take a look into the stl code). That will give you the idea how the unique_ptr works. Then try to implement your own "shared_ptr". The simplest way to implement your own shared ptr is around objects that use internal reference counting.

After you learned how they work, using either unique_ptr or shared_ptr looses it's magic and you should know which to use when.

Upvotes: 1

Related Questions