2010-12-20 17 views
3

私の現在の宿題は、リストのイテレータクラスを作成しています。私は良いerase(iterator where)関数を作成に固執しています。イテレータを使用してコンテナ要素を消去する

(質問に合わせて縮小)現在のコード:唯一の要素cases-

// Precondition: List has been checked for size > 0. 
List::iterator List::erase(List::iterator& where) 
{ 
    // Erasing only element in list. 
    if(where == end() && where == begin()) 
    { 
     pop_back(); // or pop_front(); 
     return iterator(0, this); 
    } 

    // Elem at end 
    if(where == end()) 
    { 
     pop_back(); 
     return end(); 
    } 
    else 
    { 
     // Elem at beginning 
     if(where == begin()) 
     { 
      pop_front(); 
      return ++begin(); 
     } 
    } 

    // Elem somewhere between beginning and end. 
    iterator temp(where); 
    // The node next to pCurr_ should point to the one before pCurr_ 
    where.pCurr_->next->prev = where.pCurr_->prev; 
    // The node before pCurr_ should point to the one after pCurr_ 
    where.pCurr_->prev->next = where.pCurr_->next; 
    // Return the node after pCurr_ 
    ++temp; 
    delete where.pCurr_; 
    --size_; 
    return temp; 
} 

最初の3、冒頭に終了し、要素の要素:消去がそうのように実装されていると

class List 
{ 
    class _Iter 
    { 
     friend class List; 
    public: 
     _Iter(ListElem *pCurr, List *pList); 

     /* *, ->, ++, --, == and != operators overloaded */ 

    private: 
     ListElem *pCurr_; List *pList_; 
    }; 

    typedef _Iter iterator; 

    iterator erase(iterator where); 
}; 

- 大丈夫ですか?コード化され、_Iterのメンバーへの知識と私的アクセスは絶対に必要ありません。しかし、要素がそれらの位置にない場合は、カプセル化に違反してpCurr_(リストの要素)を直接変更するという選択肢はありません。

これを避ける方法はありますか?私はSTLのリストを調べましたが、他の関数_Next_Node_(/* stuff */)_Prev_Node_(/* stuff */)を使っていましたが、あまり役に立たないものでした。 Google検索では、自分自身で書き込む方法ではなく、消去機能の使い方に関する有用な結果が得られます。

質問:pCurr_メンバーを取得せずにイテレータが指す要素を消去できる方法はありますか?

+1

STLのリストには、前のノードと次のノードの両方へのポインタがあるため、_Next_Nodeと_Prev_Node_は役に立たないわけではありません。 – DumbCoder

+0

@DumbCoder:「役に立たない」という意味ではなく、消去機能の実装を理解するのに役立たないという意味でした。 – IAE

答えて

3
  1. アンダースコアで始まり、大文字で始まる識別子は使用しないでください。標準的なライブラリとシステムライター用に予約されています。独自のリストクラスを作成していますが、実際には標準ライブラリを作成していません。

  2. end()は、通常、最後の要素ではなく、リストの最後を1つ超えた要素です。 (リストの実際の最後のイテレータを得るには、l.rbegin()。base()が起こるようにすることができます)。

  3. イテレータを非const参照ではなく値で渡します。

  4. なぜあなたはpCurrの改変に関心がありますか?

+0

コードのような感じのイモ。 1)に関しては、それは私の先生のデザインであったので、私はそれをしなければなりません。 2)のために、私はとにかくそれを変更する必要がありますが、はい、あなたは正しいです! 3)のおかげでもありがとう。 – IAE

+0

標準ライブラリではないので、テールイテレータを取得する関数を作成することもできます。必要に応じてtail()またはlast()を使用できます。私はちょうどC + +では従来の意味を持っているend()を使って "混乱しない"と言っています。 – CashCow

2

これは実際にカプセル化に違反していません。コンテナとそのイテレータが緊密に結合されていることは、かなり避けられません。その2人は一緒に実装の詳細をユーザーから隠します。彼らがお互いに友人でない場合、より多くの実装の詳細がユーザーに漏れる必要があります。 フレンドキーワードは、問題のクラスが互いの内部について知る正当な理由がある場合に、カプセル化を拡張することができます。

1つの要素を持つリストを表すbegin() == end()は、コンテナが空であることを意味する標準ライブラリの規則ではありません。 end()は、イテレータをコンテナの "one-past-the-end"に戻す必要があります。

+0

end()== begin()のことは、私のhead_とtail_ポインタを使った私の意地悪なデザインの決定のためです。私はすぐにこれを修正します。 – IAE

関連する問題