4

std::listof がありboost::shared_ptr<T>、そこから項目を削除したいのですが、リスト内の項目の 1 つに一致する T* 型のポインターしかありません。

ただしmyList.remove( tPtr )、shared_ptr は==テンプレート引数の型を実装していないため、使用できません。

私がすぐに考えたのは、どちらが構文的に正しいかを試すことでしたが、一時的に別の use_count があるmyList.remove( shared_ptr<T>(tPtr) )ため、二重削除からクラッシュします。shared_ptr

std::list< boost::shared_ptr<T> > myList;

T* tThisPtr = new T(); // This is wrong; only done for example code.
                       // stand-in for actual code in T using 
                       // T's actual "this" pointer from within T
{
   boost::shared_ptr<T> toAdd( tThisPtr ); // typically would be new T()
   myList.push_back( toAdd );
}

{
   //T has pointer to myList so that upon a certain action, 
   // it will remove itself romt the list

   //myList.remove( tThisPtr);                      //doesn't compile
   myList.remove( boost::shared_ptr<T>(tThisPtr) ); // compiles, but causes
                                                    // double delete
}  

残っている唯一のオプションは、カスタム比較で std::find を使用するか、リストの総当たりをループして自分で見つけることですが、もっと良い方法があるはずです。

明らかな何かが欠けていますか、それともこれは非標準的な使用法であり、クリーン/通常の方法で削除することはできませんか?

4

4 に答える 4

5

その通りです。ポインターを直接比較することはできません。しかし が存在しremove_if、独自の述語を指定できます。ソリューション:

template <typename T>
struct ptr_contains_predicate
{
    ptr_contains_predicate(T* pPtr) :
    mPtr(pPtr)
    {}

    template <typename P>
    bool operator()(const p& pPtr) const
    {
        return pPtr.get() == mPtr;
    }

    T* mPtr;
};

template <typename T>
ptr_contains_predicate<T> ptr_contains(T* pPtr)
{
    return ptr_contains_predicate<T>(pPtr);
}

上記の述語をヘッダーのどこかに保持するだけで、好きな場所で使用できます。

myList.remove_if(ptr_contains(tThisPtr));

shared_ptr最善の解決策は、そもそもを決して失わないことです。そのため、 をそのまま使用できますremoveが、いずれにせよ、上記は無害です。

于 2010-04-08T01:43:04.247 に答える
4

std::list のremove_ifメンバーが必要です:

述語を定義する

template <typename T> struct shared_equals_raw
{
  shared_equals_raw(T* raw)
    :_raw(raw)
    {}
  bool operator()(const boost::shared_ptr<T>& ptr) const
    {
      return (ptr.get()==_raw);
    }
private:
  T*const _raw;
};

その後、あなたは呼び出すことができます

myList.remove_if(shared_equals_raw(tThisPtr));

tThisPtr への shared_ptrs を持つノードをクリーンアップするリストを作成します。

(テストされていないため、構文上の問題を修正する必要があるかもしれません)。

ただし、enable_shared_from_this に関する Michael Burr のアドバイスは適切です。生の tThisPtr をまったく使用しない方がよいでしょう。

于 2010-04-08T01:33:30.503 に答える
3

enable_shared_from_this問題を解決することはできますが、リストで使用しているタイプはそれから派生している必要があります。

タイプがその機能を有効にしている場合は、を呼び出すことにより、オブジェクト自体から共有ポインターを取得できますshared_from_this()

于 2010-04-08T01:09:15.020 に答える
0

共有ポインタを使用して削除できますか?

std::list< boost::shared_ptr<T> > myList;

boost::shared_ptr<T> tThisPtr = new T(); 

{
    myList.push_back(tThisPtr);
}

{
    myList.remove(tThisPtr);                     
}
于 2010-04-08T03:04:16.880 に答える