Normalmente, los iteradores se utilizan para acceder a elementos de un contenedor de forma lineal; sin embargo, con los "iteradores de acceso aleatorio", es posible acceder a cualquier elemento de la misma forma que operator[]
.
Para acceder a elementos arbitrarios en un vector vec
, puede utilizar lo siguiente:
vec.begin() // 1st
vec.begin()+1 // 2nd
// ...
vec.begin()+(i-1) // ith
// ...
vec.begin()+(vec.size()-1) // last
El siguiente es un ejemplo de un patrón de acceso típico (versiones anteriores de C ++):
int sum = 0;
using Iter = std::vector<int>::const_iterator;
for (Iter it = vec.begin(); it!=vec.end(); ++it) {
sum += *it;
}
La ventaja de usar iterador es que puede aplicar el mismo patrón con otros contenedores :
sum = 0;
for (Iter it = lst.begin(); it!=lst.end(); ++it) {
sum += *it;
}
Por esta razón, es realmente fácil crear un código de plantilla que funcione igual independientemente del tipo de contenedor . Otra ventaja de los iteradores es que no asume que los datos residen en la memoria; por ejemplo, se podría crear un iterador directo que pueda leer datos de un flujo de entrada, o que simplemente genere datos sobre la marcha (por ejemplo, un generador de rango o de números aleatorios).
Otra opción usando std::for_each
y lambdas:
sum = 0;
std::for_each(vec.begin(), vec.end(), [&sum](int i) { sum += i; });
Desde C ++ 11, puede utilizar auto
para evitar especificar un nombre de tipo muy largo y complicado del iterador como se vio antes (o incluso más complejo):
sum = 0;
for (auto it = vec.begin(); it!=vec.end(); ++it) {
sum += *it;
}
Y, además, hay una variante más simple para cada variante:
sum = 0;
for (auto value : vec) {
sum += value;
}
Y finalmente, también hay std::accumulate
que tener cuidado si está agregando números enteros o de punto flotante.