6

コードで shared_ptr から auto_ptr を取得する必要があります。逆の操作を行うことができます-shared_ptrにはそのようなコンストラクターがあるため、auto_ptrをshared_ptrに変換します。

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

shared_ptr を auto_ptr に変換できますか? それとも設計上不可能ですか?

4

5 に答える 5

9

オブジェクトが他の共有ポインタと共有されている可能性があり、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!
于 2011-01-23T11:31:51.453 に答える
4

共有ポインタは多くのもので共有できますが、どうにかしてそれらすべてから取得することはできません。これはArtyompeoroによって詳述されています。

1 つの方法は、一時的な を作成し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ように扱うことができます:const auto_ptr

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

    // use a
}
于 2011-01-23T11:39:40.800 に答える
3

auto_ptrとの両方がポインタの所有権を取得するため、通常は悪い考えですshared_ptr(さまざまなポリシーに従って、ポインタの破棄などを気にします)。

2 つの異なるオブジェクトが同じポインターの所有権を保持していると、本当に良い (そして奇妙な!) 理由がない限り、実行時エラーが発生する可能性があります。

于 2011-01-23T11:31:38.857 に答える
2

aからに所有権を譲渡したい場合、これは次の場合にのみ可能です。shared_ptrauto_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.,

于 2011-01-23T12:44:01.117 に答える
1

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);
}
于 2011-01-23T11:32:39.557 に答える