开发者

No-op deallocator for boost::shared_ptr

开发者 https://www.devze.com 2022-12-28 07:44 出处:网络
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

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 avai开发者_StackOverflow社区lable.


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.


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.


  • If Boost <= 1.54, use boost/log/utility/empty_deleter.hpp.
  • If Boost == 1.55, use boost/utility/empty_deleter.hpp.
  • If Boost >= 1.56, use boost/core/null_deleter.hpp.


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.


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.


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() );
}
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号