The question arose from the need for a conditional interface. It may be so that I fell into an XY problem, but (bottom line) I ended up needing a shared pointer that would ( based on a runtime choice ) either manage or not (own or not) a resource.
The following are some thoughts on a non owning shared pointer
Using placement new, eg:
struct MyStruct {};
MyStruct ms1;
std::shared_ptr<MyStruct> sp(new(&ms1) MyStruct);
Using a dummy deleter
std::shared_ptr<MyStruct> spn(new MyStruct, [](MyStruct*){});
My class layout (where the non owning shared pointer will be used) looks like this:
template<typename T>
struct blah
{
shared_ptr<T> _m;
};
Now, the _m
member may or may not own a resource based on a runtime choice. The reason I'm not using weak_ptr
is because _m
may actually be an owning pointer.
The placement new is obviously UB, since it will in your snippet attempt to delete something on the stack. The empty deleter version will work but will allocate a reference counting block.
The trick is to use the crazy (ok, aliasing) constructor of shared_ptr
:
template< class Y >
shared_ptr( const shared_ptr<Y>& r, T *ptr );
that constructs a shared_ptr
owning what r
owns, but pointing to what ptr
points to, i.e.:
std::shared_ptr<MyStruct> sp(std::shared_ptr<MyStruct>(), p);
This is guaranteed noexcept
by the standard, and will not allocate anything. The standard even has a note that says
[ Note: This constructor allows creation of an empty
shared_ptr
instance with a non-null stored pointer. —end note ]
The placement new
will give you undefined behaviour (and likely a crash) on destruction - it will promptly call delete
on something which was not created with new
.
I'd go with the no-op deleter. The design may seem odd, but if you need such behaviour (and document it enough), it will work. I used something like this in one of my projects for a while, but then I got rid of the need for it.
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