はじめに
C++の標準ライブラリ(STL)の中心的な設計思想の一つが、「アルゴリズム」と「コンテナ」の分離です。std::sort
やstd::find
といったアルゴリズムは、std::vector
やstd::list
といった特定のコンテナに依存しません。
この両者の架け橋となるのが「イテレータ (iterator)」です。イテレータは、コンテナ内の要素の位置を示す、汎用的なポインタのようなものです。アルゴリズムは、コンテナの種類を直接知らなくても、イテレータを通じて要素にアクセスし、様々な操作を行います。
この記事では、イテレータの基本的な概念と、それがいかにしてC++の柔軟性を高めているのかを、自作のfind
アルゴリズムを例に解説します。
イテレータを使った汎用的な検索関数のサンプルコード
このコードは、任意のコンテナ(vector
とC言語スタイルの配列の両方)で使える、汎用的な検索関数 custom_find
を実装します。
完成コード
#include <iostream>
#include <vector>
#include <string>
using namespace std;
// 1. イテレータを引数に取る、汎用的な検索関数テンプレート
template <class InputIterator, class T>
InputIterator custom_find(InputIterator first, InputIterator last, const T& value) {
// firstがlastに到達するまでループ
while (first != last) {
// イテレータを間接参照(*)して、指し示す先の値を取得
if (*first == value) {
return first; // 値が見つかったら、その位置のイテレータを返す
}
// イテレータを一つ進める
++first;
}
return last; // 見つからなければ、範囲の最後の次を返す
}
int main() {
// --- std::vectorで試す ---
vector<string> items = {"りんご", "みかん", "ぶどう"};
// 2. コンテナの.begin()と.end()でイテレータを取得して渡す
auto it = custom_find(items.begin(), items.end(), "みかん");
// 3. 結果のイテレータをチェック
if (it != items.end()) {
cout << "vector内で「" << *it << "」を見つけました。" << endl;
}
// --- C言語スタイルの配列で試す ---
int numbers[] = {10, 20, 30, 40, 50};
// 2. C配列のポインタは、イテレータとして振る舞う
int* p_found = custom_find(numbers, numbers + 5, 30);
// 3. 結果のポインタをチェック
if (p_found != numbers + 5) {
cout << "C配列内で「" << *p_found << "」を見つけました。" << endl;
}
return 0;
}
コードの解説
1. 汎用的な検索関数 custom_find
template <class InputIterator, class T>
は、この関数が様々な型のイテレータや値に対応できる関数テンプレートであることを示します。
while (first != last)
: イテレータは、コンテナの「最後の要素の次」を指す特別なイテレータ(end()
が返すもの)と比較することで、範囲の終わりに達したかを判定します。*first
: ポインタと同様に、アスタリスク*
(間接参照演算子)を使って、イテレータが指し示している先の要素の値を取得します。++first
: ポインタと同様に、インクリメント++
することで、イテレータを次の要素に進めます。
2. イテレータの取得
items.begin()
,items.end()
:vector
などの標準コンテナは、.begin()
メンバ関数で先頭要素を指すイテレータを、.end()
メンバ関数で最後の要素の次を指すイテレータを取得できます。numbers
,numbers + 5
: C言語スタイルの配列では、配列名が先頭要素へのポインタとして機能し、ポインタ演算で最後の要素の次を指すことができます。ポインタもイテレータの一種です。
custom_find
関数は、引数が vector
のイテレータであろうと、C言語配列のポインタであろうと、同じように動作します。これが、イテレータを介してアルゴリズムとコンテナを分離するC++の設計の強力さです。
その他のイテレータ取得メンバ関数
関数 | 説明 |
cbegin() , cend() | 中身を変更しない読み取り専用のイテレータ (const_iterator ) を返す |
rbegin() , rend() | コンテナを逆順に辿るためのリバースイテレータを返す |
crbegin() , crend() | 読み取り専用のリバースイテレータを返す |
まとめ
今回は、C++のイテレータの基本的な概念について解説しました。
- イテレータは、コンテナの要素を指し示す、汎用的なポインタのようなもの。
*
で値にアクセスし、++
で次に進む、という統一的なインターフェースを提供する。- コンテナは
.begin()
と.end()
で、処理範囲を示すイテレータを提供する。 - この仕組みにより、アルゴリズムとコンテナが分離され、コードの再利用性が高まる。
イテレータは、C++の標準ライブラリ(STL)を効果的に使いこなす上で、避けては通れない非常に重要な概念です。