4

このようなイテレータを使用している間、

//include header files
using namespace std;

int main()
{
    map<int,int> intIntMap;
    map<int,int>::iterator pos;
    pos = intIntMap.begin();

    intIntMap[0] = 1;
    intIntMap[3] = 5;
    intIntMap[4] = 9;
    intIntMap[5] = 5;

    //遍历
    cout << (*pos).first << endl;

    while( pos != intIntMap.end() )
    {
        cout << pos->first << " <---> " << pos->second << endl;
        pos++;
    }

}

出力は4です。

しかし、私がこのようなイテレータを使用している間:

//include header file
using namespace std;

int main()
{
    map<int,int> intIntMap;
    map<int,int>::iterator pos;

    intIntMap[0] = 1;
    intIntMap[3] = 5;
    intIntMap[4] = 9;
    intIntMap[5] = 5;

    //遍历
    pos = intIntMap.begin();
    cout << (*pos).first << endl;

    while( pos != intIntMap.end() )
    {
        cout << pos->first << " <---> " << pos->second << endl;
        pos++;
    }

}

出力は私が望むものです。

イテレータの使用の違いは何ですか?新しいキーと値のペアを挿入したときに最初のイテレータはどうなりましたか?ありがとう!

追加:コンパイルはgcc 4.1.2を使用しますが、次のように混乱します。

コンパイルはgcc4.1.2を使用しますが、次のように混乱します。

4

5 に答える 5

10

コンテナが空のときに呼び出したので、 (§23.1/ 7:「コンテナが空の場合はbegin()== end()」)begin()に等しいイテレータを取得しました。end()

コンテナにアイテムを挿入してもそれは変わりませんでしたので、まだpos == intIntMap.end()です。

次に、ループのゼロ反復を実行します。これpos==end()は、ループを実行している間だけpos != end()です。

2番目の例ではpos()、データを挿入した後に設定するため、コレクションの最初のアイテムを取得し、最後まで繰り返します。

編集:地図の内容を印刷する限り、私はおそらく次のようにそれを行うでしょう:

std::ostream &operator<<(std::ostream &os, std::pair<int, int> const &d) { 
    return os << d.first << " <---> " << d.second;
}

// ...

std::copy(intIntMap.begin(), intIntMap.end(), 
          std::ostream_iterator<std::pair<int, int> >(std::cout, "\n"));
于 2012-06-24T03:56:20.703 に答える
2

これをgdbで調べてみるとfirst、キーと値のペアを追加するたびにイテレーターのフィールドが変化していることがわかりました。データが含まれていない(によって返されるbegin())マップへのイテレータには、マップ自体に関するメタデータ、具体的にはマップのサイズが含まれているようです(このfirstイテレータのフィールドは、キーと値のペアが追加されるたびに大きくなります)。begin()単一のキーと値のペアが追加された後にイテレータを取得するために呼び出すと、「予期された」動作が発生します。

于 2012-06-24T03:51:10.300 に答える
-1

イテレータは、イテレータのインスタンス化以降に変更されていないコンテナで使用することを目的としています。最初の例のコードの出力は、c ++標準に従って未定義です(希望する結果を得ることができますが、それを得ることが保証されているわけではなく、期待する理由はあまりありません)。

最初のケースではイテレータに何も起こりませんでしたが、参照する予定のコンテナが変更されており、必ずしもメモリ内の同じ場所にあるとは限りません。

于 2012-06-24T03:50:25.993 に答える
-1

コンテナを変更すると、既存のイテレータが無効になります。

一般的な方法は、使用する直前にイテレータを取得してから破棄することです。あなたはforこのように使うことができます:

#include <iostream>
#include <map>
using namespace std;

int main ()
{
  map<int, int> mymap;

  mymap[0] = 100;
  mymap[1] = 200;
  mymap[2] = 300;

  // show content:
  for (map<int, int>::iterator it = mymap.begin(); it != mymap.end(); it++)
    cout << (*it).first << " => " << (*it).second << endl;

  return 0;
}
于 2012-06-24T03:56:12.340 に答える
-1

簡単な答え:コンテナの内容を変更した後もイテレータが有効であるという保証はありません。

ここでのコンテナはmap、通常は赤黒木として実装されているため、挿入中に構造が変更され、バランスが取り直されます。

最初の例では、イテレータposをマップの先頭まで初期化しています。この時点で、イテレータは現在のコンテンツに対して有効です。beginただし、要素の追加を開始すると、イテレータは再編成されたコンテナの新しい位置を指しなくなります。

したがって、2番目の例が機能する理由はbegin、コンテナーへのすべての変更が完了した後にイテレーターをに設定しているためです。

一般に、構造を繰り返し処理しながら構造を変更することはお勧めできません。

この質問には、イテレータの有効性に関する詳細がいくつかあります。

于 2012-06-24T03:56:46.867 に答える