Convert shared_ptr to auto_ptr?

I need to get auto_ptr from shared_ptr in my code. I can do the opposite operation - convert auto_ptr to shared_ptr, since shared_ptr has such a constructor:

template<class Y> explicit shared_ptr(std::auto_ptr<Y> & r); 

Is it possible to convert shared_ptr to auto_ptr? Or is it impossible by design?

+6
c ++ shared-ptr auto-ptr
source share
5 answers

A common index can be shared by many things, you cannot just take it from them somehow. It is described by Artyom and peoro .

One approach is to create a temporary auto_ptr and free it from processing the pointer at the end of the scope. dalle describes the first approach, but it suffers from an insecurity of exceptions (it may accidentally be deleted), and it cannot protect you from accidentally passing it to a function that will (where the deletion falls out of our hands).

We can make our own wrapper to avoid this:

 template <typename T> class auto_ptr_facade { public: auto_ptr_facade(shared_ptr<T> ptr) : mPtr(ptr), mAuto(ptr.get()) {} ~auto_ptr_facade() { // doesn't actually have ownership mAuto.release(); } // only expose as const, cannot be transferred const auto_ptr<T>& get() const { return mAuto; } operator const auto_ptr<T>&() const { return get(); } private: auto_ptr_facade(const auto_ptr_facade&); auto_ptr_facade& operator=(const auto_ptr_facade&); shared_ptr<T> mPtr; auto_ptr<T> mAuto; }; 

Now you can consider shared_ptr as a const auto_ptr in scope:

 template <typename T> void foo(shared_ptr<T> ptr) { auto_ptr_facade<T> a(ptr); // use a } 
+4
source share

It is impossible by design, since the object can be shared by another common pointer and, thus, “fetching” it in auto_ptr can delete the reference object.

For the same reason, shared_ptr does not have a release function like auto_ptr.

Edit:

Even if shared_ptr had some kind of “release” method or if the link was deleted without destroying the object, it will not work for the following case (threads A, B):

 A: { A: int count = sp.use_count(); Context Switch B: shared_ptr<bar> my_sp = weak_sp.lock(); B: // now use_count = 2 but A thinks it is 1 Context Switch A: auto_ptr<bar> ap; A: if(count == 1) A: ap.reset(sp.release()); A: // actutally there is no sp.release but what if A: ap->foo(); A: } // delete the object pointer by ap as it goes out of scope Context Switch B: my_sp->foo(); // Ooops - object is deleted! 
+9
source share

This is usually a bad idea, because both auto_ptr and shared_ptr take ownership of your pointer (they will take care of destruction, etc. in accordance with different policies).

Having two different objects that own property for the same pointer will most likely lead to runtime errors if you don't do this for some really good (and weird!) Reasons.

+3
source share

Assuming you want to transfer ownership from shared_ptr to auto_ptr , this is only possible with

  • The shared_ptr reference count is 1, and
  • shared_ptr was originally created with a custom delete function, and
  • you know the type of this delete function.

Given this, here's how:

 #include <iostream> #include <boost/shared_ptr.hpp> // boost::shared_ptr #include <memory> // std::auto_ptr typedef boost::shared_ptr<int> IntSharedPtr; typedef std::auto_ptr<int> IntAutoPtr; template< class Type > void myCustomDeleter( Type* p ) { delete p; } IntSharedPtr newSharedInt() { return IntSharedPtr( new int( 42 ), &myCustomDeleter<int> ); } IntAutoPtr makeAutoFrom( IntSharedPtr& sp ) { struct Dummy { static void deleter( int* ) {} }; typedef void (*DeleterFunc)( int* ); if( sp.use_count() > 1 ) { return IntAutoPtr( 0 ); } DeleterFunc* d = boost::get_deleter<DeleterFunc>( sp ); if( d == 0 ) { return IntAutoPtr( 0 ); } int* const p = sp.get(); *d = &Dummy::deleter; sp.reset(); return IntAutoPtr( p ); } template< class T > T& refTo( T const& r ) { return const_cast< T& >( r ); } int main() { IntAutoPtr p( makeAutoFrom( refTo( newSharedInt() ) ) ); std::cout << (p.get() == 0? "Failed" : "Worked" ) << std::endl; } 

Note: this method is not thread safe.

Cheers and hth.,

+2
source share

You should not do this because auto_ptr gets ownership of the pointer.

But you can do it, but make sure you call release before you go out of scope.

 void foo(shared_ptr<Y> s) { auto_ptr<Y> a(s.get()); // use a a.release(); } 

EDIT: The above solution is not safe for everyone. The following should work, combining the protection class with the guarantee that const auto_ptr cannot be copied:

 void bar(const auto_ptr<Y>& p); struct as_const_auto_ptr { explicit as_const_auto_ptr(const shared_ptr<Y>& p) : p(p), a(p.get()) {} ~as_const_auto_ptr() {a.release();} operator const auto_ptr<Y>&() {return a;} const shared_ptr<Y> p; auto_ptr<Y> a; }; void foo(shared_ptr<Y> s) { as_const_auto_ptr a(s); // use a. bar(a); } 
+1
source share

All Articles