2012-01-09 5 views
1

std::mapまたはstd::vectorまたはそれに含まれるiteratorのいずれかのコンテナを反復している間に、container<>::endのようなものではなくvariable.end()と照合されます。例えば、iterator :: end()はなぜ非staticメンバーで、string :: nposと似ていないのですか?

map<int, int> var; 
for(map<int, int>::iterator it = var.begin(); it != var.end(); it++) 
...           ^^^^^^^^^^^^^^^ 

は、上記の部分を強調することはできませんのようなものに:静的メンバstring::nposに似て

it != map<int,int>::end 

。コンテナベースのタイプごとではなく、可変ベースごとに.end()を提供するという設計上の決定の背後にある理由は何ですか? (すなわち、map<int,int>::endmap<int,double>::endは異なるであろう。しかし、すべてmap<int,int>変数について、::endも同様であろう。)

+3

'begin()'がインスタンスメソッドになるのは面倒ですが、 'end'は静的メンバーですか? 'rbegin()'と 'rend()'はどうでしょうか? –

+1

この質問は理にかなっていません。これが有益な具体的な事例はありますか? – Pubby

+1

@Pubby、いくつかのアプリケーションでは、 'end'と関数の戻り値を直接比較できます。このような場合には、関数のローカルな変数名は必要ありません。 – iammilind

答えて

3

イテレータは、反復するために、前後に移動します。増分および減分(双方向反復子)操作を提供する必要があります。 end()イテレータをデクリメントすると、コンテナの最後の項目に移動します。これにより、後方への反復が可能になります。

あなたの提案について。これを実装することは、各イテレータがそれと共にエンドイテレータを持ち、それが格納している実エンドイテレータと等しいとき、スタティックエンドイテレータと等しいと比較することを意味します。実際には、静的な終了イテレータはすべて異なるタイプにする必要はありません。なぜなら、その "イテレータ"はそれ以外のものには使用できないからです。

このような設計は、実装するのが面倒で、使用するのが無駄になるだけです。各イテレータがコンテナの終わりを知っている必要がある場合は、任意の範囲を指定するために、未使用のイテレータを2つ追加する必要があります。

+0

ニースの答え、私はそのバックワード*ポイントを完全に逃した。 – iammilind

7

このように、いくつかのアレイベースの容器は単に要素へのポインタとしてイテレータを実装できます。 1つ前の要素ポインタは、各配列ごとに異なります。

+0

これは唯一の真の答えだと思います。単純なコンテナ実装との下位互換性。 – Spidey

5

は、次の2つのアレイ考えてみましょう:2つの配列の最後の要素を過ぎ

int a1[] = {2, 3, 4}; 
int a2[] = {5, 6, 7}; 

一つを異なっている:あなたが他のために1つのポインタを使用することはできません

int *p1 = a1 + 3; // for a1 
int *p2 = a2 + 3; // for a2 

。配列の終わりを表す普遍定数はありません。以下は間違っている:

for (int *p = a1; p != a2; p++) 

コンテナのイテレータの同じ種類の同じend()を持っていないの説明が類似しています。

+0

ポインタ演算はバイト単位ではなく、 'int * p1 = a1 + 3'でなければなりません。 – Pubby

+0

@Pubby:ありがとう。編集されました。 :D – Donotalo

関連する問題