2015-11-11 9 views
15

私は、標準ではSTLコンテナを実装する必要があるとは言いませんが、むしろSTLコンテナがそれぞれの要件を満たすことを要求しています。STLはどのようにコンテナの終わりを知っていますか?

しかし、STLオーダーコンテナは、通常、red–black treesとして実装されていることが広く知られています。

std::setまたはstd::mapの要素を、それぞれのイテレータを使用して、またはC++ 11以降では巡回ループを使用して繰り返し処理できます。

しかし私が困惑しているのは、STLの注文したコンテナが「終了」を "知っている"ということです。または、別の言い方をすると、それらはツリーとして実装されているので、 コンテナの最後がどのように実装されているのか、それとも が実装できますか?

私は標準が§23.2.1/ C一般的なコンテナの要件を規定することを知っている強調鉱山):

)は(開始 コンテナ内の最初の要素を参照する反復子を返します。 end()は、コンテナの終わりの値 であるイテレータを返します。コンテナが空の場合、begin()== end();

OK、連続したコンテナの場合、これは簡単ですが、この「過去の終わり」をツリーでどのように実現できるのでしょうか?

+6

"過去の最後"は論理的な概念であり、物理的な概念ではないことを理解してください。これは、文字通り最後の有効なエントリを通過したときに取得するイテレータを意味しますが、そのイテレータの内部コンテンツは何でもかまいません。 –

+0

breadth-firstやdepth-firstのような終端ツリートラバーサルからのnext()とend()の自然な概念があります。したがって、それぞれのイテレーターについて概念的に特別なものはありません。 –

+0

@ MarkRansom十分に公正、それは論理的な概念です。しかし、どのようにそのような論理的な概念を実装するのですか?私はコードで意味します。 – 101010

答えて

3

ユーザーがend()を得ることができますので、終了をセンチネルノードのいくつかの種類を持っている容器の中に何かを挿入し、イテレータをデクリメントするには、この必要性のような「リストのような」コンテナのすべて、および減算end()必見ポイントその挿入された要素に追加します。私の理解は、いくつかの実装がこれに動的に割り当て、いくつかは動的なセンチネルノードをコンテナ自体の中に置くことです。

+0

は、私は 'のstd ::マップ::エンド()'や 'のstd ::セット::終了は、()' decrementableイテレータを返さなければならないことを意味し、標準で場所を見つけることができないんです。あなたは 'basic_string'、' array'、 'deque'、' list'と 'vector'では本当のことを言っていますが、OPは' set'と 'map'について尋ねました。 АндрейБеньковский@ –

+0

:N4527 23.2.1 [container.requirements.general]/12:特記のない限り、[...]コンテナのメンバ関数を呼び出す[...]に イテレータを無効、またはオブジェクトの値を変更してはなりませんその容器内にある。 - そしてmap :: insertは明示的にそれ以外のことを述べません。 23.2.4 [associative.reqmts]/9:挿入と据え付けるメンバーは、コンテナにイテレータと参照の有効性に影響を与えないものとし、消去メンバーは消去要素にのみイテレータと参照を無効にするものとします。 АндрейБеньковский@ –

+0

: - 再配分が挿入反復子によってトリガされ、参照が無効にされる場合は、これらの例では特に、それは* basic_string'、 'deque'、または' 'vector'ための*真実ではありません。そして、あなたは '配列 'に挿入することはできませんので、ここではあまり関係ありません。 –

9

Visual Studio 2013 STLでmapコンテナの実装を検査しましたが、ここにはendが実装されています。 mapが構築されると、RBツリーの先頭要素が割り当てられ、この要素はコンテナの終わりと宣言される。

有効なイテレータを使用してコンテナをトラバースすると、operator++operator--は単にhead要素をスキップします。ツリーの最後の要素に到達し、イテレータをインクリメントすると、それは上向きに移動し(右のサブツリーを探して)、最終的にツリーの先頭に到達します。これはendです。

関連する問題