将shared_ptr转换为auto_ptr?

ks1*_*322 6 c++ auto-ptr shared-ptr

我需要在我的代码中从shared_ptr获取auto_ptr.我可以做反向操作 - 将auto_ptr转换为shared_ptr,因为shared_ptr有这样的构造函数:

template<class Y> explicit shared_ptr(std::auto_ptr<Y> & r);
Run Code Online (Sandbox Code Playgroud)

我可以将shared_ptr转换为auto_ptr吗?或者设计不可能?

Art*_*yom 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!
Run Code Online (Sandbox Code Playgroud)

  • @timday使用weak_ptr时可能导致竞争条件的唯一问题.例如,如果当前计数为1,但在其他线程中,弱指针的某个用户创建shared_ptr,它可能变为2,并且您之前的检查将无效. (2认同)

GMa*_*ckG 4

共享指针可以被很多东西共享,你不能以某种方式从它们那里获取它。Artyompeoro详细阐述了这一点。

一种方法是创建一个临时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;
};
Run Code Online (Sandbox Code Playgroud)

现在您可以在范围内将 a 视为 , shared_ptrconst auto_ptr

template <typename T>
void foo(shared_ptr<T> ptr)
{
    auto_ptr_facade<T> a(ptr);

    // use a
}
Run Code Online (Sandbox Code Playgroud)