5

リスト内の項目へのポインターp(イテレーターではない) があります。pその後、リストから項目を削除 (消去) することはできますか? 何かのようなもの:

mylist.erase(p);

これまでのところ、場所のアイテムに到達するまでリストを反復処理し、メソッドpを使用することによってのみこれを行うことができましたがerase、これは非常に非効率的です。

4

4 に答える 4

9

いいえ、イテレータを使用する必要があります。イテレータを取得するよりもポインタを取得する方が簡単な理由はわかりません...

于 2012-09-18T14:34:31.780 に答える
3

Astd::listは連想的ではないため、ポインターをキーとして使用して特定の要素を直接削除することはできません。

この状況に陥っているという事実は、コレクションからアイテムをそのまま削除する唯一の方法は、それを完全に反復すること (つまり、線形の複雑さ) であることは正しいため、むしろ疑わしい設計を示しています。

次のことを検討する価値があります。

  1. 可能であれば、std::multiset直接アクセスをより効率的にするリストを (重複するアイテムがあると仮定して) に変更できます。

  2. 設計が許す場合は、指しているアイテムを変更して「削除済み」フラグを組み込む (またはこれを提供するテンプレートを使用する) ことで、コレクションからオブジェクトを削除することを回避しながら、すぐに削除済みとしてマークすることができます。欠点は、この規則に対応するためにすべてのソフトウェアを変更する必要があることです。

  3. これが線形検索の唯一のビットであり、コレクションが大きくない場合 (<20 アイテムなど)、便宜上、提案したように線形検索を実行しますが、コードに大きなコメントを残して、どのように " 「これがどれほど非効率的か」を完全に理解してください。いずれにしても、しばらくの間、これが具体的な問題にならないことに気付くかもしれません。

おそらく3がベストな選択肢だと思います。:)

于 2012-09-18T14:52:45.063 に答える
1

これは私がアドバイスすることではありませんが、質問に答えるだけです:

未定義の動作と移植性のない禁止された世界に入る準備ができている場合にのみ読んでください:

T*の要素へのポインタからイテレータを作成する移植性のない方法がありますlist<T>liststd ライブラリのヘッダー ファイルを調べる必要があります。定義がどこにあるGnu g++かが含まれているためです。ほとんどの場合、次のようなノードで構成されます。stl_list.hstd::liststd::list<T>

template <class T>
struct Node {
   T item;
   Node* prev;
   Node* next;
};

このノードポインタNode<T>::itemを計算することで、あなたへのポインタを持つことができます。offsetofこのNodeテンプレートは の非公開部分である可能性があるstd::listため、これをハックする必要があることに注意してください。たとえば、同一の構造体テンプレートを別の名前で定義してみましょう。std::list<>::iteratorthis の単なるラッパーnodeです。

于 2012-09-18T17:59:27.667 に答える