C++ 是否将共享\u ptr转换为自动\u ptr?

C++ 是否将共享\u ptr转换为自动\u ptr?,c++,shared-ptr,auto-ptr,C++,Shared Ptr,Auto Ptr,我需要从代码中的共享\u ptr获取自动\u ptr。我可以执行反向操作-将自动\u ptr转换为共享\u ptr,因为共享\u ptr具有以下构造函数: template<class Y> explicit shared_ptr(std::auto_ptr<Y> & r); 模板显式共享ptr(std::auto_ptr&r); 我可以将共享\u ptr转换为自动\u ptr吗?或者它是设计上不可能的?通常这是一个坏主意,因为auto\u ptr和share

我需要从代码中的共享\u ptr获取自动\u ptr。我可以执行反向操作-将自动\u ptr转换为共享\u ptr,因为共享\u ptr具有以下构造函数:

template<class Y> explicit shared_ptr(std::auto_ptr<Y> & r);
模板显式共享ptr(std::auto_ptr&r);

我可以将共享\u ptr转换为自动\u ptr吗?或者它是设计上不可能的?

通常这是一个坏主意,因为
auto\u ptr
shared\u ptr
都拥有指针的所有权(根据不同的策略,他们会关心销毁指针和其他东西)


如果两个不同的对象拥有同一指针的所有权,则很可能会导致运行时错误,除非您出于某些真正好的(和奇怪的!)原因而这样做。

设计上是不可能的,因为该对象可能与其他共享指针共享,因此将其“获取”到auto_ptr可能会导致删除引用的对象

出于同样的原因,shared_ptr没有像auto_ptr那样的“release”成员功能

编辑:

即使shared_ptr有某种“release”方法或允许删除其引用 如果不销毁对象,它将无法用于以下情况(线程A、B):

A:{
A:int count=sp。使用_count();
上下文切换
B:shared_ptr my_sp=weak_sp.lock();
B://现在使用_count=2,但A认为是1
上下文切换
A:自动ptr ap;
A:如果(计数=1)
答:ap.reset(sp.release());
A://实际上没有sp.release,但如果
A:ap->foo();
A:}//在对象指针超出范围时由ap删除它
上下文切换
B:my_sp->foo();//对象被删除!

您不应该这样做,因为
auto\u ptr
拥有指针的所有权

但您可以这样做,但请确保在超出范围之前调用
release

void foo(shared_ptr<Y> s)
{
    auto_ptr<Y> a(s.get());

    // use a

    a.release();
}

一个共享的指针可以被很多东西共享,你不能从他们身上拿走它。这是由和详细阐述的

一种方法是创建一个临时的
自动\u ptr
,并将其从处理作用域末尾的指针中释放出来。概述了第一种方法,但这种方法缺乏异常安全性(可能会意外删除),并且无法保护您不意外地将其传递给将要转移所有权的函数(我们无法控制删除)

我们可以制作自己的包装来避免这种情况,不过:

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;
};
假设您希望将所有权从
共享\u ptr
转移到
自动\u ptr
,则只有在

  • 共享\u ptr
    的参考计数为1,并且
  • shared_ptr
    最初是使用自定义删除函数创建的,并且
  • 您知道删除器函数的类型
有鉴于此,以下是如何:

#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;
}
#包括
#包括//boost::共享\u ptr
#包括//标准::自动
typedef boost::shared_ptr IntSharedPtr;
typedef std::auto_ptr IntAutoPtr;
模板<类类型>
无效myCustomDeleter(类型*p)
{
删除p;
}
IntSharedPtr新闻共享()
{
返回IntSharedPtr(新int(42)和myCustomDeleter);
}
IntAutoPtr makeAutoFrom(IntSharedPtr&sp)
{
结构虚拟
{
静态void deleter(int*){}
};
typedef void(*DeleterFunc)(int*);
如果(sp.use_count()>1){return IntAutoPtr(0);}
DeleterFunc*d=boost::get_deleter(sp);
如果(d==0){return IntAutoPtr(0);}
int*const p=sp.get();
*d=&Dummy::deleter;
sp.reset();
返回IntAutoPtr(p);
}
模板
T&refTo(T常数&r){return const_cast(r);}
int main()
{
IntAutoPtr p(makeAutoFrom(refTo(newSharedInt()));

std::cout,如果在
//期间引发异常,请使用
?@ybungalobill:如果我意外地按值将其传递给函数?:)此解决方案太容易出错。@GMan:它不是异常安全的,但正如@ybungalobill所指出的,请使用一个保护对象。@GMan:好吧,恢复我的投票。尽管它做了问题中提出的事情,但它是安全的依赖无用的东西!@GMan:但正如我所说的,你不应该这样做,但这仍然是可能的。@GMan:但是,如果它过期,指针对象就已经被ptr.reset()删除,结果变成了一个悬空的指针。所以在几乎任何有用的情况下,ptr都将是作为参数传递的共享ptr的副本:
尝试\u make\u auto\u ptr(my\u local\ptr)
,所以它不会过期。@ybungalobill:噢,duh,哈哈。Sleepy.:)我已经扩展了dalle的答案。-当前代码中的1
ptr
是按值传递的。这几乎确保了它不是唯一的引用。而且,使用
弱ptr
代码不必要地低效。我认为原始作者是Java人。
shared\ptr::use_count
对于
boost::shared_ptr
和C++0x
std::shared_ptr
都存在。最后,
重置
会破坏引用的对象。哦…@Gman:好的,全新的方法。我删除了我的否决票!:-)顺便说一句,如果你知道
shard_ptr
的deleter函数的类型,那么你可以重新设置ally夺走所有权。但是通过公共界面,这只有在创建时指定了自定义销毁函数时才可能。我记得我为此极力主张保留
get\u deleter
功能。但是如果默认deleter func的类型可用,那就太好了!干杯,分享了\u ptr的“唯一性”方法原则上可以告诉您共享的\u ptr是否有对对象的唯一剩余引用,在这种情况下,传输到自动\u ptr似乎更合理一些。但是如果没有任何支持的API(即发布方法),就没有办法。(根据我的经验,使用unique或count的共享\u ptr代码通常会出错)。@timday unique的问题是,当使用弱\u ptr时,它可能会导致争用条件。例如,如果当前计数为1,但在其他线程中,弱指针的某个用户创建共享\u ptr,则它可能会变为2,并且您之前的检查将为2
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;
};
template <typename T>
void foo(shared_ptr<T> ptr)
{
    auto_ptr_facade<T> a(ptr);

    // use a
}
#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;
}