問題の歴史:
C++98のSTLに登場したイテレーターは、具体的なデータ構造から抽象化し、コンテナの要素に統一的にアクセスすることを可能にしました。C++20の採択により、標準の範囲が追加され、コンテナの操作における表現力と安全性が向上しました。
問題:
イテレーターの不適切な使用は、ランタイムエラーを引き起こす原因となります:コンテナの境界を超える、変更後の無効化など。異なる種類のイテレーターをサポートしていることで、互いに混同された場合、予期しない動作が生じることがあります。begin()/end()を手動で使用することは規律を必要とします。
解決策:
コンテナの機能に合ったイテレーターのタイプを使用する(例えば、ランダムアクセスはvector/deque/arrayにのみ)。無効なイテレーターを保持しない。現代的な課題では、標準化された範囲とアルゴリズムを使用することが一般的です。
コード例:
#include <vector> #include <algorithm> #include <iostream> #include <ranges> int main() { std::vector<int> vec{1, 2, 3, 4, 5}; // イテレーターによるイテレーション for (auto it = vec.begin(); it != vec.end(); ++it) { std::cout << *it << " "; } // 範囲によるイテレーション for (int x : vec | std::ranges::views::filter([](int v){return v % 2 == 0;})) { std::cout << x << " "; } return 0; }
主な特徴:
push_backの呼び出し後にstd::vectorのイテレーターに何が起こりますか?
push_backの後にコンテナが拡張される場合(リバランス)、すべての古いイテレーターと参照は無効になります。capacityが変更されないpush_backの後は、イテレーターは保持されます。変更の間でイテレーターを保持しない方が安全です。
ランダムアクセスイテレーターは双方向イテレーターと何が違いますか?
ランダムアクセスは、算術演算(it + n)およびインデックスによるアクセス(it[n])をサポートし、双方向イテレーターは++と--のみをサポートします。すべてのSTLコンテナがランダムアクセスをサポートしているわけではありません。
標準アルゴリズムSTLは通常のポインタで動作しますか?
はい、ポインタはC++において完全にランダムアクセスイテレーターの要件を満たします。
std::listをループしている間に、開発者はeraseメソッドを使用してコンテナを直接変更し、イテレーターを更新せず、ランタイムエラーを引き起こします。
長所:
短所:
コンテナを変更する前に、常に次のイテレーターを保存します。標準的なアルゴリズムerase-remove idiomをvectorに、またはlist::remove_ifをリストに使用します。
長所:
短所: