我需要在我的代码中从 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 吗?还是设计上不可能?
我需要在我的代码中从 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 吗?还是设计上不可能?
这在设计上是不可能的,因为该对象可能与其他共享指针共享,因此将其“获取”到 auto_ptr 可能会导致删除引用的对象。
出于同样的原因,shared_ptr 没有作为 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!
共享指针可以被许多东西共享,你不能只是以某种方式从它们中获取它。这是由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;
};
现在您可以在范围内处理 a shared_ptr
like a const auto_ptr
:
template <typename T>
void foo(shared_ptr<T> ptr)
{
auto_ptr_facade<T> a(ptr);
// use a
}
通常这是一个坏主意,因为两者都auto_ptr
拥有shared_ptr
您的指针的所有权(根据不同的政策,他们会关心销毁它和其他东西)。
拥有两个不同的对象持有同一个指针的所有权可能会导致运行时错误,除非您出于某些非常好的(而且很奇怪!)的原因这样做。
假设您想将所有权从 a转移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;
}
注意:这种技术不是线程安全的。
干杯&hth.,
你不应该这样做,因为auto_ptr
它需要指针的所有权。
但是您可以做到,但请确保release
在超出范围之前致电。
void foo(shared_ptr<Y> s)
{
auto_ptr<Y> a(s.get());
// use a
a.release();
}
编辑:上述解决方案并非异常安全。以下应该可以工作,将保护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);
}