I have functions that take in std::shared_ptr as an argument so I am forced to use std::shared_ptr, but the object I am passing to the function is not dynamically allocated. How do I wrap the object in std::shared_ptr and have std::shared_ptr not call delete on it.
-
possible duplicate of [How to release pointer from boost::shared\_ptr?](http://stackoverflow.com/questions/1525764/how-to-release-pointer-from-boostshared-ptr) – Will Dean Nov 21 '13 at 21:11
-
@WillDean not a duplicate, this question has nothing to do with boost library. – Ken Li Nov 21 '13 at 21:12
-
2@KenLi Except that `std::shared_ptr` and `boost::shared_ptr` are virtually identical. – Angew is no longer proud of SO Nov 21 '13 at 21:12
-
2boost::shared_ptr was basically the prototype for what became std::shared_ptr. – Will Dean Nov 21 '13 at 21:13
-
11This is a horrible idea. The only reason for a function to accept a `shared_ptr` is if it intends to store a reference to the pointee (i.e., share ownership). Invalidating the object while that reference is stored somewhere will not go well. If the function in question does **not** store a reference, it should not accept an owning pointer type. – Casey Nov 21 '13 at 21:29
-
6A use case for this is where you have something like `FILE *` where the type can either be managed (e.g. via `fopen`) or not (e.g. `stdin`) and you have a class that uses the object beyond the call that created it (e.g. creating a parser or logger). In that case, you would want to pass a "do nothing" deleter with stdin, but an `fclose` deleter with an `fopen`ed file. – reece Mar 25 '17 at 17:37
-
4@Casey A real life application I have come across where this idea makes sense is with a `shared_ptr
`. I may have a function that takes an ostream and stores a reference to it as a shared pointer for later use. Now let's say I want to output to `std::cout`. I cannot delete `std::cout`, but I can guarantee that it will exist for at least as long as my function will retain the shared pointer. – Cort Ammon Mar 09 '18 at 18:04 -
1@CortAmmon: Agree. I came to this question from here: https://stackoverflow.com/questions/2159452/c-assign-cin-to-an-ifstream-variable ... which is about passing `std:cin` or an opened file (`std::ifstream`). – kevinarpe Apr 25 '20 at 12:54
6 Answers
MyType t;
nasty_function(std::shared_ptr<MyType>(&t, [](MyType*){}));

- 239,200
- 50
- 490
- 574

- 49,529
- 25
- 126
- 221
-
2@Angew: No coincidence. Just plain copy and paste. Demonstrates a more C++11ish alternative. – ronag Nov 21 '13 at 21:12
-
8Note: Any function you pass a shared_ptr to might also grab ownership of the object, so the OP needs to make sure that either (a) that is not happening or (b) the lifetime of the object is longer than the lifetime of everything that has shared ownership of it. – Nevin Nov 21 '13 at 23:16
Specify a no-op deleter when creating the shared pointer. E.g. like this:
void null_deleter(MyType *) {}
int main()
{
MyType t;
nasty_function(std::shared_ptr<MyType>(&t, &null_deleter));
}

- 167,307
- 17
- 350
- 455
The best way to do this is to use the aliasing constructor:
nasty_function(std::shared_ptr<MyType>(std::shared_ptr<MyType>{}, &t));
Compared to the null deleter approach, this doesn't need to allocate a control block, and is noexcept
.
As noted by @Casey and @Nevin, this should only be done when you are sure that the function won't attempt to take shared ownership, or if the object would outlive everything that might "own" it.
-
Great hint. As a note on versions: this is [a feature of Cx+11](http://www.codesynthesis.com/~boris/blog/2012/04/25/shared-ptr-aliasing-constructor/) but also available from boost 1.35 as `nasty_function(boost::shared_ptr
(boost::shared_ptr – radke Aug 23 '16 at 16:33(), &t));` -
1I just want to add a note about @T.C's answer using the aliasing constructor. If you use this technique, you will not be able to take a `std::weak_ptr` on the resulting `std::shared_ptr`. – kctigerhawk Dec 15 '16 at 14:41
-
Boost.Core provides a null_deleter
function object exactly for this purpose.
Citing the documentation:
The header
<boost/core/null_deleter.hpp>
defines theboost::null_deleter
function object, which can be used as a deleter with smart pointers such asunique_ptr
orshared_ptr
. The deleter doesn't do anything with the pointer provided upon deallocation, which makes it useful when the pointed object is deallocated elsewhere.
Example from the documentation:
std::shared_ptr< std::ostream > make_stream()
{
return std::shared_ptr< std::ostream >(&std::cout, boost::null_deleter());
}

- 599
- 4
- 12
-
Alas, this still does not have appeared to made it into the std.... – David V. Corbin Mar 22 '23 at 17:21
You can do this trick:
A a;
shared_ptr<A> pa(&a);
foo(pa);
new (&pa) shared_ptr<A>(); // pa "forgets" about a

- 33
- 1
-
Placement new to overwrite the pointer without calling its destructor. Clever. Purely academically (because the entire question is pretty horrible): any idea whether this has well-defined behaviour? – Thomas Apr 18 '16 at 10:31
-
@Thomas Of course not. The second line is UB already (for breaking a Requires clause on the constructor); you don't even need the placement new. – T.C. Apr 18 '16 at 10:40
-
1
i was just searching for a solution, saw this question. found nothing and made a great one this is my code
class HBitmap : public shared_ptr<HBITMAP__>
{
public:
HBitmap();
HBitmap(HBITMAP Handle);
bool autoDelete = true;
};
Win32::HBitmap::HBitmap(HBITMAP Handle)
: shared_ptr<HBITMAP__>(Handle, [&](HBITMAP hBitmap) {if(autoDelete)DeleteObject(hBitmap);})
{
}
this solution is a combination of lambda expressions and inheritance.
very well formed. fast. you can't expect anything more. not only you can set the deleter, but if you do some modifications, you can use a std::function<void(pointer)>
as a custom deleter. with lambdas you can run free and do what ever you want.

- 171
- 3
- 7