SvinSimpe
SvinSimpe

Reputation: 870

Multiple instances holds a reference to a unique_ptr

I'm moving with the times and thought I should start a new project with the goal to use and expose myself to smart pointers more. I'm thinking of a large pool of unique_ptrs storing collision components. These components will be passed by const ref to a quad tree that internally perform read-only ops on the ptrs.
I've written a simplified example to reflect the intentions of my implementation.

struct Owner
{
    unique_ptr<int> uPtr;
};

struct SomeContainer
{
    list<const unique_ptr<int>*> uPtrList;

    void Insert( const unique_ptr<int>& borrowedUPtr )
    {
        list.push_back( &borrowedUPtr );
    }

    void DoSomething()
    {
        for( const auto& ptr : uPtrList )
            // Perform read ops
    }
};

These are my intentions: Owner owns the unique_ptr and thereby controls its lifetime. SomeContainer will store a const reference to the pointer since it's not permitted to neither reset nor modify the pointer in any way.
Is this a viable approach or am I disturbing the force?

Upvotes: 3

Views: 1806

Answers (2)

Rosme
Rosme

Reputation: 1049

I see two possible solutions.

One of them could be that your owner has a std::shared_ptr and SomeContainer keep a list of std::weak_ptr, something like this:

struct Owner
{
    std::shared_ptr<int> uPtr;
};

struct SomeContainer
{
    list<std::weak_ptr<int>> uPtrList;

    void Insert( std::shared_ptr<int> borrowedUPtr )
    {
        list.push_back( std::weak_ptr<int>(borrowedUPtr) );
    }
    //...
};

Another one could be that SomeContainer keep a list of const raw pointer obtained through std::unique_ptr::get. Since Owner has the ownership, if you can guarantee that Owner will live as long or longer than SomeContainer, there is nothing wrong with such strategy. Personnaly, I prefer this one:

struct Owner
{
    unique_ptr<int> uPtr;
};

struct SomeContainer
{
    list<const int*> uPtrList;

    //Could also be directly passed as a const int*
    void Insert( const unique_ptr<int>& borrowedUPtr )
    {
        list.push_back( borrwedUPtr.get() );
    }
    //...
};

Upvotes: 4

Chris Drew
Chris Drew

Reputation: 15334

It is not clear why you need to use smart pointers here at all. A simple member variable expresses ownership just fine:

struct Owner
{
    int value;
};

And then observers can store a raw-pointer:

struct SomeContainer
{
    list<const int*> ptrList;

    void Insert( const int& borrowedValue)
    {
        ptrList.push_back( &borrowedValue);
    }

    void DoSomething()
    {
        for( const auto& ptr : ptrList)
            // Perform read ops
    }
};

This is assuming you can be confident that owner will stay alive whilst the observers wish to observe. If you can't be confident of that then unique_ptr will not help you and you will need some something like weak_ptr with shared_ptr.

Upvotes: 2

Related Questions