C++のSTLには、様々な便利な機能が用意されています。
その中でもイテレーターは、コンテナ内の要素を順番にアクセスするための重要な概念です。
本記事では、イテレーターの基礎から始めて、STLで提供される各種イテレーターの種類や使い方について詳しく解説していきます。
イテレーターとは
イテレーターとは、コンテナ内の要素に順番にアクセスするためのオブジェクトです。
STL(Standard Template Library)では、様々な種類のコンテナが用意されており、それぞれに対応したイテレーターが提供されています。
イテレーターを使用することで、コンテナ内の要素を簡単かつ効率的に処理することができます。
また、イテレーターはポインターのようなものであり、ポインター演算子を使用して要素にアクセスすることも可能です。
次の章では、STLで提供される主なイテレーターについて説明します。
イテレーターの種類
C++のSTL(Standard Template Library)には、様々な種類のイテレーターがあります。
イテレーターとは、コンテナ内の要素にアクセスするためのポインターのようなもので、STLでは標準的な方法でコンテナを操作するために使用されます。
C++で扱うイテレーターは主に以下の5種類が存在します。
- 入力イテレーター
- 出力イテレーター
- 前方イテレーター
- 双方向イテレーター
- ランダムアクセスイテレーター
入力イテレーター
入力イテレーターは、読み取り専用であることを示すものです。これらは、単方向リストや配列などのシーケンスコンテナで使用されます。入力イテレーターを使用して、コンテナ内の要素を1つずつ読み取ることができます。
出力イテレーター
出力イテレーターは、書き込み専用であることを示すものです。これらは、配列やリストなどのシーケンスコンテナで使用されます。出力イテレーターを使用して、新しい要素を追加したり既存の要素を変更したりすることができます。
前方イテレーター
前方イテレーターは、順方向に移動することができる単方向リストやフォワードリストなどのシーケンスコンテナで使用されます。前方イテレーターを使用して、先頭から末尾まで順番にアクセスすることができます。
双方向イテレーター
双方向イテレーターは、前後両方向に移動することが可能な双方向リストやデック(deque)などのシーケンスコンテナで使用されます。双方向性を持つために前後両方向へ移動可能です。
ランダムアクセスイテレーター
ランダムアクセスイテレーターは最も高度な種類です。これらはランダムアクセス可能な配列やベクタ(vector)等でも使われています。ランダムアクセス性能が高くO(1)時間計算量かかる演算子(+,-,+=,-=,<,>,<=,>=,[])が使えるため効率的です。
以上がC++ STL の主要な5種類のイテレーターです。
イテレーターの使い方
イテレーターは、コンテナ内の要素にアクセスするためのポインターのようなものです。イテレーターを使用することで、コンテナ内の要素を簡単に操作することができます。
イテレーターの宣言
イテレーターを宣言するには、まずコンテナを定義します。次に、そのコンテナからイテレーターを作成します。以下は、vectorコンテナからイテレーターを作成する例です。
#include <iostream>
#include <vector>
int main() {
std::vector<int> vec = {1, 2, 3, 4, 5};
std::vector<int>::iterator it = vec.begin();
return 0;
}
上記の例では、std::vector<int>::iterator
を使用して vec
コンテナからイテレーター it
を作成しています。また、begin()
メソッドを使用して最初の要素に対応するイテレーターを取得しています。
イテレーターの移動
イテレーターは、前方向や後方向へ移動させることができます。以下は、前方向へ移動させる例です。
#include <iostream>
#include <vector>
int main() {
std::vector<int> vec = {1, 2, 3, 4, 5};
std::vector<int>::iterator it = vec.begin();
// イテレーターを前方向へ移動
++it;
return 0;
}
上記の例では、++it;
を使用して it
イテレーターを前方向へ移動させています。
イテレーターの比較
イテレーター同士を比較することができます。以下は、二つのイテレーターが等しいかどうか判断する例です。
#include <iostream>
#include <vector>
int main() {
std::vector<int> vec = {1, 2, 3, 4, 5};
std::vector<int>::iterator it1 = vec.begin();
std::vector<int>::iterator it2 = vec.end();
if (it1 == it2) {
std::cout << "it1 and it2 are equal" << std::endl;
} else {
std::cout << "it1 and it2 are not equal" << std::endl;
}
return 0;
}
上記の例では、==
演算子を使用して it1
イテレーターと it2
イテレーターが等しいかどうか判断しています。
イテレーターの参照
イテレーターポインタ自体だけでなく、ポインタが指す値も取得できます。以下は、現在位置にある値を取得する例です。
#include <iostream>
#include <vector>
int main() {
std::vector<int> vec = {1, 2, 3, 4, 5};
std::vector<int>::iterator it = vec.begin();
// 現在位置にある値を取得
int value = *it;
return 0;
}
上記の例では、*
演算子を使用して現在位置(vec
の先頭要素)にある値(つまり1
)を取得しています。
取得できる値は、イテレーターを移動させることで変更させられます。
#include <iostream>
#include <vector>
int main() {
std::vector<int> vec = {1, 2, 3, 4, 5};
std::vector<int>::iterator it = vec.begin();
// 現在位置にある値を取得
int value1 = *it++; // 1
int value2 = *it++; // 2
int value3 = *it++; // 3
int value4 = *it++; // 4
int value5 = *it; // 5
return 0;
}
イテレーターの変更
イテレーターポインタ自体だけでなく、ポインタが指す値も変更できます。以下は、vecの先頭要素を1
から10
に変更する例です。
#include <iostream>
#include <vector>
int main() {
std::vector<int> vec = {1, 2, 3, 4 ,5};
std::vector<int>::iterator it = vec.begin();
// 値`1`から`10`に変更
*it = 10;
return 0;
}
上記の例では、*
演算子と代入演算子(=) を使用して現在位置にある値(つまり3
)から10
に変更しています。
ループ処理
イテレーターはfor文やwhile文で現在位置から終端までループさせることができます。
#include <iostream>
#include <vector>
int main() {
std::vector<int> vec = { 1, 2, 3, 4 ,5 };
std::vector<int>::iterator it = vec.begin();
while (it != vec.end()) {
std::cout << *it << std::endl;
it++;
}
return 0;
}
1
2
3
4
5
イテレーターが指す値を順番に参照にしていきたい場合は、上記のようにループさせることで効率よく処理を行えます。