Reputation: 870
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_ptr
s 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
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
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