我需要在我的代码中从shared_ptr获取auto_ptr。我可以做反向操作 - 将auto_ptr转换为shared_ptr,因为shared_ptr有这样的构造函数:
template<class Y> explicit shared_ptr(std::auto_ptr<Y> & r);
我可以将shared_ptr转换为auto_ptr吗?或者设计不可能?
答案 0 :(得分:9)
设计是不可能的,因为对象可能与其他共享指针共享,因此将其“提取”到auto_ptr可能会导致删除引用的对象。
出于同样的原因,shared_ptr没有“release”成员函数作为auto_ptr。
修改强>
即使shared_ptr有某种“释放”方法或允许删除它的引用 在不破坏对象的情况下,它不适用于以下情况(线程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!
答案 1 :(得分:4)
共享指针可以被很多东西共享,你不能以某种方式从它们中获取它。这由Artyom和peoro详细说明。
一种方法是创建一个临时的auto_ptr
,并将其从处理范围末尾的指针中释放出来。 dalle概述了第一种方法,但是这种方法缺少异常安全(可能会意外删除),并且它无法保护您不会意外地将其传递给将要转移所有权的功能(删除不属于我们的手)。
我们可以制作我们自己的包装器以避免这种情况:
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;
};
现在,您可以在范围内将shared_ptr
视为const auto_ptr
:
template <typename T>
void foo(shared_ptr<T> ptr)
{
auto_ptr_facade<T> a(ptr);
// use a
}
答案 2 :(得分:3)
通常这是一个坏主意,因为auto_ptr
和shared_ptr
都取得指针的所有权(他们会关心根据不同的政策销毁它和东西)。
让两个不同的对象持有相同指针的所有权可能会导致运行时错误,除非你为了一些非常好的(以及奇怪的!)原因这样做。
答案 3 :(得分:2)
假设您要将所有权从shared_ptr
转移到auto_ptr
,这只有在
shared_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;
}
注意:此技术不是线程安全的。
干杯&amp;第h。,
答案 4 :(得分:1)
你不应该这样做,因为auto_ptr
取得了指针的所有权。
但你可以这样做,但请确保在超出范围之前致电release
。
void foo(shared_ptr<Y> s)
{
auto_ptr<Y> a(s.get());
// use a
a.release();
}
编辑:以上解决方案不是例外安全。以下内容应该有效,将 guard 类与无法复制const auto_ptr
的保证相结合:
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);
}