イテレータとは?

テーマ:

標準C++の基本で、中心的概念です。

最初は分かりづらいかもしれませんが、ぜひぜひ覚えることをお勧めします。(^^)


簡単に言うと、以下のようになるかと思います。


 配列やリストのようにデータがいくつか連なっているもの(格納庫)に対して、

 どの格納庫に対してもすべて同じ方法で、順番にアクセスする方法



「どの格納庫に対しても同じ方法で」というところがミソで、再利用性と可読性を高めます。

格納庫とは、具体的には以下のようなものです。

  ・string

  ・vector

  ・list

   など


【使用例】

//#include <cstdlib>
//#include <iostream>


  vector<int> vec;
  vector<int>::iterator i;
  int sum = 0;


  //準備。値を入れてみる
  vec.push_back(1);
  vec.push_back(2);
  vec.push_back(3);


  //メイン 。イテレータで順にアクセスして足し算。
  for(i=vec.begin(); i!=vec.end(); ++i){
    sum += *i;
  }

  cout << sum << endl;



【出力】

6


【説明】

配列に入れた数値をすべて足し合わせてます。

え!?何か面倒になっただけじゃないの?と思うかもしれませんが、もう少しお待ちください。

それぞれ分解してみて見ます。


vector<int>::iterator i;

  vector<int>::iteratorはvectorのイテレータの型を表します。

  ここで宣言されたi は、配列の要素ひとつを表すポインタのように扱えます

  ですのでこの場合、*i は、int型になります。

  vector以外の場合も、格納庫::iterator のように格納庫のイテレータ型を宣言します。


forの中の vec.begin()

  vector配列の先頭のイテレータを返します。


forの中の vec.end()

  vector配列の一番最後の要素の次の要素を返します。

  どうして最後ではなくて、最後の次なのかというと、

  イテレータの比較演算子は普通、「!=」「==」くらいしか存在しないので

  forでまわすときに、end()が最後の要素を返すと最後の1つが処理されないことになるからです。


++i

  イテレータを次に進めます。

  ポインタだと思えば、次のポインタに進めたように見えます。

  イテレータはポインタのように扱えるように設計されています。


sum += *i;

  イテレータに*演算子を作用させると、ポインタに*を作用させたときと同じになります。

  ここでは、intの配列のイテレータなので、int型になります。



難しそうに見えるイテレータもポインタと思えば、理解できれば、見やすいと思いません?

普通、型が違うと、すべて違う書き方で書かないといけなかったりするのが

プログラム言語の常だったりしますが、イテレータは違います。

stringもvectorもlistもすべて同じ書き方で書けます!


同じ書き方で書けると言う事は、templateを使用して1つ関数を書いておけば

それをいくらでも再利用できると言うことです。



漏補

漏:

イテレータはポインタのようです、と述べましたが例外があります。

イテレータには種類があって、種類によっては代入でポインタの位置を取っておくことができないものが

あります。

普通ポインタであれば、以下のようにすると位置を取っておけます。

  char* p = "abcd";

 p1 = p;

  ++p;


  *p1⇒'a'  保存した位置を保持してます。

  *p ⇒'b' 1つ進んだ位置を保持してます。


 ところが、++pでひとつ進めることで、p1も同じ位置まで移動してしまうイテレータがあるのです。

 たとえば、istream_iteratorです。


補:

これも、気をつけるしかありません。

イテレータがどのような種類なのか。位置を他の変数に代入したときに、保持できるのかを把握しておくことが

重要です。




参考:

・自作のイテレータを作成するには?  

イテレータ

デザインパターン
AD