Biblioteca estándar de C++<iterator>
En la biblioteca estándar de C++<iterator>El archivo de cabecera proporciona un conjunto de herramientas para recorrer los elementos de los contenedores. Los iteradores son uno de los conceptos centrales de la Biblioteca de Plantillas Estándar (STL) de C++, que permiten a los programadores acceder a los elementos de un contenedor de manera uniforme, sin necesidad de preocuparse por los detalles específicos de implementación del contenedor.
Un iterador es un objeto que proporciona un método para recorrer los elementos de un contenedor. Un iterador puede considerarse como un puntero a los elementos de un contenedor, pero es más flexible y potente que un puntero. Los iteradores se pueden utilizar para acceder y modificar los elementos de un contenedor, y también se pueden usar junto con los algoritmos de STL.
Los iteradores se dividen principalmente en las siguientes categorías:
- Iterador de entrada (Input Iterator): solo puede realizar operaciones de lectura individuales y no puede realizar operaciones de escritura.
- Iterador de salida (Output Iterator): solo puede realizar operaciones de escritura individuales y no puede realizar operaciones de lectura.
- Iterador directo (Forward Iterator): puede realizar operaciones de lectura y escritura, y puede moverse hacia adelante.
- Iterador bidireccional (Bidirectional Iterator): además de poder realizar todas las operaciones de un iterador directo, también puede moverse hacia atrás.
- Iterador de acceso aleatorio (Random Access Iterator): además de poder realizar todas las operaciones de un iterador bidireccional, también puede realizar acceso aleatorio, por ejemplo, acceder a los elementos mediante un índice.
Funciones comunes (punto clave)
| Función | Propósito | Ejemplo | Descripción |
|---|---|---|---|
std::advance(it, n) |
Mover el iterador n pasos | advance(it, 2); |
Modifica el iterador original |
std::distance(a, b) |
Calcula la distancia entre dos iteradores | distance(v.begin(), v.end()); |
Devuelve el número de elementos |
std::next(it, n) |
Devuelve un nuevo iterador n pasos hacia adelante | auto it2 = next(it, 2); |
Recomendado, no modifica el valor original |
std::prev(it, n) |
Devuelve un nuevo iterador n pasos hacia atrás | auto it2 = prev(it, 1); |
Disponible desde C++11 |
Adaptadores de iteradores (muy importantes)
Los adaptadores de iteradores pueden cambiar el comportamiento de los iteradores, adaptándolos a diferentes escenarios de uso.
| Adaptador | Propósito | Ejemplo |
|---|---|---|
std::back_inserter |
Inserción al final (llama a push_back) | back_inserter(vec) |
std::front_inserter |
Inserción al principio (llama a push_front) | front_inserter(list) |
std::inserter |
Inserción en una posición específica | inserter(vec, it) |
Iteradores de flujo (la herramienta definitiva para simplificar IO)
| Tipo | Propósito | Ejemplo |
|---|---|---|
std::istream_iterator |
Lee datos del flujo de entrada | istream_iterator<int>(cin) |
std::ostream_iterator |
Escribe en el flujo de salida | ostream_iterator<int>(cout, " ") |
Sintaxis de los iteradores
La sintaxis de los iteradores suele ser la siguiente:
#include <iterator>
// 使用迭代器遍历容器
for (ContainerType::iterator it = container.begin(); it != container.end(); ++it) {
// 访问元素 *it
}
Ejemplo
A continuación se muestra un ejemplo que utiliza el<iterator>archivo de cabecera y el recorrido con iteradoresstd::vector:
Ejemplo
#include <vector>
#include <iterator>
#include <algorithm>
int main() {
// Crear un contenedor vector e inicializarlo
std::vector<int> vec = {1, 2, 3, 4, 5};
// Usar iteradores para recorrer el vector
for (std::vector<int>::iterator it = vec.begin(); it != vec.end(); ++it) {
std::cout << *it << " ";
}
std::cout << std::endl;
// Usar la palabra clave auto para simplificar el tipo de iterador
for (auto it = vec.begin(); it != vec.end(); ++it) {
std::cout << *it << " ";
}
std::cout << std::endl;
// Usar el bucle for basado en rangos de C++11
for (int elem : vec) {
std::cout << elem << " ";
}
std::cout << std::endl;
// Usar back_inserter para insertar automáticamente
std::vector<int> v2;
std::fill_n(std::back_inserter(v2), 3, 100);
// Usar ostream_iterator para generar la salida
std::copy(v2.begin(), v2.end(),
std::ostream_iterator<int>(std::cout, " "));
std::cout << std::endl;
return 0;
}
Resultado de salida:
1 2 3 4 5 1 2 3 4 5 1 2 3 4 5 100 100 100
Resumen
<iterator>El propósito principal se puede resumir en tres puntos:
- Método de acceso unificado: diferentes contenedores usan la misma lógica de recorrido
- Desacoplar contenedores y algoritmos: los algoritmos solo dependen de los iteradores
- Mejorar la reutilización del código: el mismo código se puede aplicar a múltiples estructuras de datos
Para los principiantes, se recomienda dominar primero lo siguiente:
next / prev / distanceback_inserter- Métodos de recorrido con iteradores