17

Is there a stock no-op deallocator in Boost to use with boost::shared_ptr for static objects, etc.

I know it's ultra-trivial to write, but I don't want to sprinkle my code with extra tiny functions if there is already one available.

Alex B
  • 82,554
  • 44
  • 203
  • 280
  • 4
    If the object need not be destructed, then why are you putting it into a shared_ptr in the first place? – Billy ONeal Apr 26 '10 at 03:01
  • 5
    Very handy if you've gone overboard with smart pointers everywhere, and you want to pass a stack or member variable to a function that requires `shared_ptr`. – Mark Ransom Apr 26 '10 at 03:02
  • 1
    @Mark Ransom: You make me think of codebases that make me cringe. :P – Billy ONeal Apr 26 '10 at 03:16
  • 6
    @Billy ONeal: if you haven't seen a codebase that makes you cringe, you haven't been in the business long enough. I've not only seen them, I've written them. – Mark Ransom Apr 26 '10 at 03:20
  • @Mark Ransom: I've written them too. It helps in the care and feeding of my delete key. – Billy ONeal Apr 26 '10 at 03:21
  • The problem is that you need to know the function that takes shared_ptr won't store it somewhere to use later, as the normal promise is that the underlying is valid until the last shared_ptr is destroyed which won't be the case for your stack variable. – CashCow Feb 12 '14 at 11:03

6 Answers6

10

Yes there is one here:

#include <boost/serialization/shared_ptr.hpp> // for null_deleter

class Foo
{
  int x;
};

Foo foo;
boost::shared_ptr< Foo > sharedfoo( &foo, boost::serialization::null_deleter() );

There is, of course, a danger with the fact that you need to know the function you call doesn't store the shared_ptr for later use, as it actually goes against the policy of shared_ptr in that the underlying object remains valid until that of the last instance of the shared_ptr.

CashCow
  • 30,981
  • 5
  • 61
  • 92
3

Solution uses Boost.Lambda:

#include <boost/shared_ptr.hpp>
#include <boost/lambda/lambda.hpp>

int main()
{
    int *p = new int(5);

    {
        boost::shared_ptr<int> sp(p, boost::lambda::_1);
    }

    delete p;
}

'boost::lambda::_1' creates an empty functor that takes one argument.

You'll probably want to put a //comment in there to let people know why you did it, though.

scjohnno
  • 149
  • 4
2
Alexander Shukaev
  • 16,674
  • 8
  • 70
  • 85
1

Wouldn't it be cleaner just to take an extra reference so the deallocator is never called? (Although that's still not very clean.)

I can't say that there's no function in Boost which would do the job, but it doesn't sound like something they would want to include.

EDIT: Having read the comments and a little documentation, it boils down to this:

  1. Reference leaking. At some point, execute this:

    new shared_ptr( my_global_shared_ptr );
    

    Advantages: conceptually easy. Disadvantages: you are leaking something on the heap.

  2. Custom deallocator. Since shared_ptr requires little of the deallocator function, an anonymous identity function like that provided in the other answer would do fine.

    Advantages: leverages Boost and has absolutely no overhead. Disdvantages: requires a little documentation.

  3. Non-static global object. If there is a global shared_ptr for your object, that should be the only means of access to it. Replace the declaration of the global with a shared_ptr intialized by new my_class. I think this is best.

Potatoswatter
  • 134,909
  • 25
  • 265
  • 421
1

There's a ticket for this on the Boost bug tracker: https://svn.boost.org/trac/boost/ticket/1913 - no activity for a long time until some murmur two weeks ago.

John Zwinck
  • 239,568
  • 38
  • 324
  • 436
0

FWIW, this what I'm using. I use it in unit tests to adapt a local into a shared_ptr.

// The class NoOp_sptr_Deleter can be used to construct a shared_ptr<>()
// that will NOT delete the pointee.
// This can be helpful in unit-testing. Wrapping a local as a shared_ptr.
// Do take care with the lifetimes though.
struct NoOp_sptr_Deleter
{
    void operator()(void const *) const {}
};

template<typename T>
boost::shared_ptr<T> FakeSharedPtrFromRef(T& aRef)
{
    return boost::shared_ptr<T>(&aRef, NoOp_sptr_Deleter() );
}
MartinP
  • 688
  • 1
  • 8
  • 17
  • The OP specifically asked for solutions that are already provided by Boost or the stdlib. He *knows* that it's ultra trivial to write such a function / functor. – Xeo Dec 25 '11 at 11:14