STL の配列をイテレータで繰り返し処理する - C++ プログラミング

PROGRAM


STL の配列をイテレータで繰り返し処理する

C++ の STL (Standard Template Library) に用意されている std::vector や std::list などでは、繰り返し処理を支援するイテレータという機能が用意されています。

イテレータというのは、配列のどの要素であるかを示す情報で、加減算を使うことで指し示す要素の位置を移動することができます。

 

例えば std::vector 型であれば、最初の要素を指し示すイテレータを begin メソッドで取得することができます。

また、最後の要素の次を示すイテレータを end メソッドで取得することができるので、begin から end のひとつ手前までをひとつずつ進めながら値を参照することで、最初から最後までを繰り返して処理できます。

// イテレータを格納する変数を準備します。

std::vector<CMyClass>::iterator iterator;

 

// 最初のイテレータから、最後のイテレータになるまで、イテレータを一つずつ先に進めます。

for (iterator = vector->begin(); iterator != vector->end(); ++iterator)

{

// ここで、要素毎の操作を行います。

CMyClass* element = &(*iterator);

 

}

この例では vector という名前の std::vector<CMyClass> 型の変数があったときに、それの最初の要素から最後の要素までを for 構文で繰り返して取得しています。

for の終了条件として "iterator != vector->end()"、すなわち「末尾を示すイテレータが現れるまで」と指定していますが、end メソッドで取得できる位置は最後の要素の一つ先なので、このような条件判定でも最後の要素を取り逃すことはありません。

for でループする度に実行するコードは "++iterator" となっていますが、これはイテレータに 1 を加えると次の要素を指すようになるというのを利用しています。

 

このような機能を使ってループを書けばいいので、同じことが while ループでも行えます。

// イテレータを格納する変数を準備します。

std::vector<CMyClass>::iterator iterator = vector.begin();

 

// 最後のイテレータになるまで繰り返します。

while (iterator != vector.end())

{

// ここで、要素毎の操作を行います。

CMyClass* element = &(*iterator);

 

 

 

// イテレータを一つずつ先に進めます。

iterator++;

}

やっていることは for 構文のときと同じなので、難しいことはないと思います。

 

リバースイテレータ

ちなみにこのイテレータ、std::vector<T> では逆順のものも取得できるようになっています。

その時に使うのが、逆順の先頭を取得する rbegin メソッドと、逆順の末尾(逆順で見たときの最後の要素の次)を取得する rend メソッドがそれで、このメソッドを実行することで、逆順を扱うリバースイテレータを取得できます。

// リバースイテレータを格納する変数を準備します。

std::vector<CMyClass>::reverse_iterator iterator;

 

// 最初のリバースイテレータから、最後のリバースイテレータになるまで、リバースイテレータを一つずつ先に進めます。

for (iterator = vector->rbegin(); iterator != vector->rend(); ++iterator)

{

// ここで、要素毎の操作を行います。

CMyClass* element = &(*iterator);

 

}

リバースイテレータの型は std::vector<T>::reverse_iterator となっていて、通常のイテレータとは違う方になっています。

このリバースイテレータは、足して行くほどに逆順に辿るようになっています。通常の begin メソッドで取得できるイテレータから 1 を引いても end にはならないため、逆順に辿りたい場合はこちらを使うようにするのが簡単です。

 

読み取り専用イテレータ

std::vector<T> が const 指定された場合には、取得できるイテレータの型が変わります。

通常の std::iterator は std::const_iterator 型になり、std::reverse_iterator は std::const_reverse_iterator になります。

// イテレータとその読み取り専用イテレータの例

std::vector<CMyClass>::iterator iterator;

std::vector<CMyClass>::const_iterator constIterator;

 

// リバースイテレータとその読み取り専用イテレータの例

std::vector<CMyClass>::reverse_iterator reverseIterator;

std::vector<CMyClass>::const_reverse_iterator constReverseIterator;

読み取り専用の std::vector<T> から取得したからといって、イテレータも読み取り専用になっているわけではなく、加減算でちゃんと位置を移動させることができるようになっています。

通常のイテレータとの違いは、管理している要素のポインタが const 指定になるため、要素への直接代入や、要素がクラスインスタンスだった場合は const 指定のメソッド以外は呼び出せないようになるところです。


[ もどる ]