views:

427

answers:

4

I have a list of smart pointers. I want some of these smart pointers to act as regular pointers, meaning they are simply a reference to an instance and are not involved in its deallocation. They might for example point to instances allocated on the stack. The other smart pointers in the list should act as regular boost::shared_ptr.

Here is how the class might look:

template<class T> smart_ptr {
private:
    T *p;
    boost::shared_ptr<T> sp;
public:
    smart_ptr(T *p): p(p), shared(0) { } // p will not be deleted
    smart_ptr(boost::shared_ptr<T> &sp): p(sp.get()), sp(sp) { }
    T *get() const { return p; }
}

If there is a boost class that does this, I would prefer to use it instead of writing a class myself. It appears there are none, or am I mistaken?

+10  A: 

One constructor for shared_ptr takes the destructor method, and you can pass in an empty functor.

Using Custom Deallocator in boost::shared_ptr

(You want just an empty function.)

280Z28
But can you mix and match shared_ptrs with different deleters in the same list? They become different types, right?
Kim Gräsman
No, the deleter isn't part of the type of `shared_ptr`, so yes, you can mix and match different deleters in the same collection.
@mmutz: thanks, I see how that works now!
Kim Gräsman
I believe the TR1 standard rules this technique out; deleting the pointer is required to be well-defined even if you specify a custom destructor function.
Daniel Earwicker
@Earwicker: no it doesn't, thank goodness (Earwicker deleted the answer saying this, but not the comment).
Steve Jessop
+1  A: 

This sounds like a boost::weak_ptr: http://www.boost.org/doc/libs/1_35_0/libs/smart_ptr/weak_ptr.htm

But you can only create a weak_ptr from a shared_ptr, so as for your stack-allocated objects, I'm not sure how that would work.

Kim Gräsman
+2  A: 

I've got this little class in my toolbox for this:

struct nodelete {
    template <typename T>
    void operator()( T * ) {}
};

Usage:

int main() {
    SomeClass sc;
    boost::shared_ptr<SomeClass> p( &sc, nodelete() );
    // ...
}
A: 

This smells of bad design.

I can't think of a reasonable situation where you wouldn't want to delete the pointer. Here are the (unreasonable IMO) situations:

1) static duration objects. Instead, consider using a singleton mixin (use CRTP to mixin the singleton that has an instance() method that returns a copy of a local static shared_ptr<>; local statics are thread unsafe so you'll also need an appropriate static mutex if this could be called by multiple threads). The benefit of using a proper singleton is that your singleton will be destructed at exit after other objects that continue to hold shared_ptr<>'s to it.

2) objects created on the stack. Just don't do this. Instead create the object on the heap protected by a shared_ptr<>. If you need to create shared_ptr<>'s to the object in different parts of the code (i.e. you can't take copies from an original shared_ptr<>) then inherit from boost::enable_shared_from_this<> and get shared_ptr<>'s from shared_from_this().

Is there some other reason you want a shared_ptr<> that doesn't ever delete anything?

James Taylor