Normalmente, os iteradores são usados para acessar elementos de um contêiner de maneira linear; entretanto, com "iteradores de acesso aleatório", é possível acessar qualquer elemento da mesma maneira que operator[]
.
Para acessar elementos arbitrários em um vetor vec
, você pode usar o seguinte:
vec.begin() // 1st
vec.begin()+1 // 2nd
// ...
vec.begin()+(i-1) // ith
// ...
vec.begin()+(vec.size()-1) // last
A seguir está um exemplo de um padrão de acesso típico (versões anteriores de C ++):
int sum = 0;
using Iter = std::vector<int>::const_iterator;
for (Iter it = vec.begin(); it!=vec.end(); ++it) {
sum += *it;
}
A vantagem de usar o iterador é que você pode aplicar o mesmo padrão a outros contêineres :
sum = 0;
for (Iter it = lst.begin(); it!=lst.end(); ++it) {
sum += *it;
}
Por esse motivo, é realmente fácil criar um código de modelo que funcione da mesma forma, independentemente do tipo de contêiner . Outra vantagem dos iteradores é que ele não assume que os dados residem na memória; por exemplo, pode-se criar um iterador direto que pode ler dados de um fluxo de entrada ou que simplesmente gera dados em tempo real (por exemplo, um intervalo ou gerador de números aleatórios).
Outra opção usando std::for_each
e lambdas:
sum = 0;
std::for_each(vec.begin(), vec.end(), [&sum](int i) { sum += i; });
Desde C ++ 11, você pode usar auto
para evitar a especificação de um nome de tipo muito longo e complicado do iterador como visto antes (ou ainda mais complexo):
sum = 0;
for (auto it = vec.begin(); it!=vec.end(); ++it) {
sum += *it;
}
E, além disso, há uma variante mais simples para cada:
sum = 0;
for (auto value : vec) {
sum += value;
}
E, finalmente, há também std::accumulate
onde você deve ter cuidado ao adicionar números inteiros ou números de ponto flutuante.