logo

Iteradores em C++ STL

Um  iterador em C++  é um objeto semelhante a um ponteiro que aponta para um elemento do contêiner STL. Eles geralmente são usados ​​para percorrer o conteúdo do contêiner STL em C++. A principal vantagem dos iteradores STL é que eles tornam os algoritmos STL independentes do tipo de contêiner usado. Podemos simplesmente passar o iterador para os elementos do contêiner em vez do próprio contêiner para os algoritmos STL.

Declaração do Iterador

Cada contêiner em C++ STL possui seu próprio iterador. Portanto, temos que declarar um iterador como:



C++
<type>::iterator it; 

onde

  • tipo: Tipo de contêiner para o qual o iterador é declarado.
  • isto: Nome atribuído ao objeto iterador.

Podemos então inicializá-lo atribuindo algum iterador válido. Se já tivermos um iterador a ser atribuído no momento da declaração, podemos pular a declaração de tipo usando o comando auto palavra-chave.

C++
auto it = iter 

onde iterar é o iterador atribuído ao iterador recém-criado.



Nosso Curso C++ aborda o uso de iteradores no STL garantindo que você entenda como percorrer diferentes tipos de contêineres.

Exemplo de iteradores

O programa abaixo ilustra como usar o iterador para percorrer o contêiner de vetor:

C++
#include    using namespace std; int main() {  vector<int> v = {1 2 3 4 5};  // Defining an iterator pointing to  // the beginning of the vector  vector<int>::iterator first =  v.begin();  // Defining an iterator pointing  // to the end of the vector  vector<int>::iterator last =  v.end();    // Iterating the whole vector  while(first != last) {  cout << *first << ' ';  first++;  }  return 0; } 

Saída
1 2 3 4 5 

Como você deve ter notado, usamos vector::begin() e vector::end() função. Essas funções são funções-membro de std::vector que retorna o iterador para o primeiro e um elemento após o último elemento do vetor. Usamos o retorno dos iteradores como essas funções para iterar os vetores.



Funções do iterador de contêiner

C++ STL fornece algumas funções-membro em Contêiner STL que retornam os iteradores para pelo menos o primeiro e o último elemento. Essas funções-membro são definidas em quase todos os contêineres STL (deixando alguns contêineres de acesso limitado, como pilha fila ) com o mesmo nome para consistência.

A tabela a seguir lista todos os métodos que retornam o iterador aos contêineres:

Função Iteradora

Valor de retorno

começar()

Retorna um iterador para o início do contêiner.

fim()

Retorna um iterador para o elemento teórico logo após o último elemento do contêiner.

cbegin()

Retorna um iterador constante para o início do contêiner. Um iterador constante não pode modificar o valor do elemento para o qual está apontando.

um pouco()

pandas criando dataframe

Retorna um iterador constante para o elemento teórico logo após o último elemento do contêiner.

rbegin()

Retorna um iterador reverso para o início do contêiner.

renderizar()

Retorna um iterador reverso para o elemento teórico logo após o último elemento do contêiner.

crbegin()

Retorna um iterador reverso constante para o início do contêiner.

CRENDO()

Retorna um iterador reverso constante para o elemento teórico logo após o último elemento do contêiner.

Por exemplo se uma coisa é o nome do vetor, então podemos usar os métodos acima, conforme mostrado abaixo:

C++
vec.begin() vec.rbegin() vec.cbegin() vec.crbegin() vec.end() vec.rend()  vec.cend() vec.crend() 

Operações de Iteradores

Assim como a aritmética de ponteiros, existem algumas operações que são permitidas em iteradores C++. Eles são usados ​​para fornecer diferentes funcionalidades que aumentam a importância dos iteradores. Existem 5 válidos operações de iterador em C++ :

  • Desreferenciando Iteradores
  • Iteradores de incremento/decremento
  • Adicionando/subtraindo números inteiros a iteradores
  • Subtraindo outro iterador
  • Comparando Iteradores

Desreferenciando Iteradores

A operação de desreferenciação permite que os usuários acessar ou atualizar o valor do elemento apontado pelo iterador. Nós usamos o (*) operador indireto para desreferenciar iteradores como ponteiros.

C++
// Access *it; // Update *it = new_val;  

onde novo_val é o novo valor atribuído ao elemento apontado pelo iterador isto .

Iteradores de incremento/decremento

Podemos aumentar ou diminuir o iterador em 1 usando Operadores (++) ou (--) respectivamente. A operação de incremento move o iterador para o próximo elemento no contêiner enquanto a operação de decremento move o iterador para o elemento anterior.

C++
it++; // post-increment ++it; // pre-increment it--; // post-decrement --it; // pre-decrement 

Adicionando/subtraindo números inteiros a iteradores

Também podemos adicionar ou subtrair um valor inteiro dos iteradores. Será mais a posição seguinte ou anterior do iterador de acordo com o valor inteiro adicionado.

C++
// Addition it + int_val;  // Subtraction it - int_val;  

onde int_val são os valores inteiros que estão sendo adicionados ou subtraídos do iterador isto .

Subtraindo outro iterador

Podemos subtrair um iterador de outro para encontrar a distância (ou o número de elementos) entre a memória para a qual eles estão apontando.

C++
it1 - it2 

Comparando Iteradores

Também podemos testar os dois iteradores do mesmo tipo um contra o outro para encontrar o relacionamento entre eles. Podemos usar operadores relacionais como (==) operadores de igualdade e (!=) operadores de desigualdade junto com outros operadores relacionais, como< > <= >=.

C++
it1 != it2 // Equal to it1 == it2 // Not equal to it1 > it2 // Greater than it1 < it2 // Less than it1 >= it2 // Greater than equal to it1 <= it2 // Less than equal to 

Tipos de iteradores em C++

Os iteradores STL podem ser divididos com base nas operações que podem ser executadas neles. Existem 5 tipos principais de iteradores em C++ listados na tabela abaixo junto com contêineres suportados e operações de iterador suportadas.

Iterador

Descrição

Contêineres Suportados

Operações Suportadas

Iterador de entrada

É um iterador unidirecional usado para ler os valores.

Fluxo de entrada

Desreferenciando igualdade de incremento

Iterador de saída

Também é um iterador unilateral, mas usado para atribuir os valores. Ele não pode acessar os valores.

Fluxo de saída

Incremento de desreferenciação (somente gravação)

Iteradores avançados

Ele pode acessar e também atribuir os valores. É a combinação do iterador de entrada e saída.

forward_list unordered_map unordered_set

Desreferenciando igualdade de incremento

Iteradores bidirecionais

Ele pode se mover em ambas as direções, para frente ou para trás. Os contêineres como conjunto de lista e multimapa suportam iteradores bidirecionais.

lista mapa conjunto multimapa multiset

Desreferenciando a igualdade de incremento/decremento

Iteradores de acesso aleatório

Iteradores de acesso aleatório são iteradores que podem ser usados ​​para acessar elementos distantes do elemento para o qual apontam, oferecendo a mesma funcionalidade dos ponteiros.

string de matriz deque de vetor

lista java para array

Todos

Como podemos ter notado na tabela acima, além dos iteradores de entrada e saída à medida que avançamos na tabela, o tipo de iterador contém os recursos do iterador acima, juntamente com alguns novos recursos.

Adaptadores Iteradores

Adaptadores de iteradores em C++ são o tipo especial de iteradores criados sobre iteradores tradicionais para fornecer funcionalidade especializada. Existem muitos adaptadores iteradores em C++, alguns dos quais são fornecidos abaixo:

Tipo de adaptadores iteradores

Descrição

Iterador reverso

O iterador reverso é construído sobre o tipo de operador bidirecional ou superior e permite aos usuários percorrer o contêiner na direção reversa.

Iteradores de fluxo

Os iteradores de fluxo, nomeadamente os iteradores istream e ostream, são construídos nos iteradores de entrada e saída, respectivamente. Esses iteradores permitem que os usuários usem os fluxos como contêineres.

Mover Iteradores

Iteradores de movimento são usados ​​para introduzir a semântica de movimento em algoritmos STL. Os iteradores de movimentação movem a propriedade dos dados do contêiner copiado para o contêiner de cópia sem criar cópias extras.

Iterador de inserção

Os iteradores de inserção permitem inserir os elementos fornecidos em alguma posição do contêiner. Existem três iteradores de inserção em C++:

  1. back_insert_iterador: Inserções na parte traseira do recipiente.
  2. front_insert_iterador: Inserções na frente do contêiner.
  3. inserir_iterador: Insere em qualquer lugar do contêiner.

Esses iteradores podem ser criados usando back_inserter() front_inserter() inserir() funções em C++.

Funções utilitárias do iterador em C++

C++ STL fornece várias funções para simplificar o trabalho com iteradores. Eles estão listados na tabela abaixo:

Função Descrição Sintaxe
std::avançar Avança um iterador em um número específico de posições. avançar ( isso n )
std::próximo Retorna o iterador que está um número especificado de posições à frente do iterador fornecido. próximo ( isso n )
Padrão :: Anterior Retorna o iterador que está em um número especificado de posições atrás do iterador fornecido. anterior ( isso n )
std::distância Retorna o número de elementos entre dois iteradores. distância ( isso1 isso2 )
std::começarRetorna um iterador para o primeiro elemento do contêiner fornecido. começar ( recipiente )
std::fimRetorna um iterador para o elemento após o último elemento do contêiner fornecido. fim ( recipiente )
std::rbeginRetorna um iterador reverso para o último elemento do contêiner fornecido. começar ( recipiente )
std::rendRetorna um iterador reverso para o elemento que precede o primeiro elemento do contêiner fornecido. faz ( recipiente )
std::inseridor Cria um iterador de inserção que insere elementos em um contêiner em uma posição especificada. insersor ( posição do contêiner )
std::back_inserter Cria um iterador de inserção posterior que anexa elementos ao final de um contêiner. back_inserter ( recipiente )
std::front_inserter Cria um iterador de inserção frontal que insere elementos na frente de um contêiner. front_inserter ( recipiente )

Aplicações de Iteradores com Exemplos

Iteradores são amplamente usados ​​em C++ para muitas finalidades diferentes ao trabalhar com contêineres e algoritmos STL. A seguir estão algumas aplicações principais de iteradores em C++ com seus exemplos de código:

Atravessando Contêineres

Atravessar contêineres STL é a aplicação mais básica de iteradores. Neste usamos as funções Begin() e End() para fazer com que os iteradores de início e fim percorram todo o contêiner. Basicamente, continuamos incrementando o iterador inicial até que não seja igual ao final.

Exemplo

C++
#include    using namespace std; int main() {  set<int> s = {10 20 30   40 50};  // Iterator to the beginning   // of the set  auto it = s.begin();  // Iterating through the   // entire set  while (it != s.end()) {    // Dereferencing iterator   // to access value  cout << *it << ' ';    // Incrementing the   // iterator  it++;  }    return 0; } 

Saída
10 20 30 40 50 

Conforme mostrado no código acima, percorremos o contêiner definido. Da mesma forma, podemos usar a mesma abordagem para percorrer qualquer contêiner.

Invertendo um contêiner

Os iteradores reversos permitem percorrer um contêiner do final ao início sem a necessidade de lidar manualmente com a reversão.

Exemplo

C++
#include    using namespace std; int main() {  vector<int> vec = {10 20 30   40 50};  // Defining reverse iterators   // pointing to the reverse   // beginning of vec  auto it = vec.rbegin();  // Iterating the whole   // vector in reverse  while (it != vec.rend()) {  cout << *it << ' ';  it++;  }  return 0; } 

Saída
50 40 30 20 10 

Algoritmos Independentes de Contêiner

Os iteradores permitem que algoritmos funcionem com qualquer tipo de contêiner, tornando funções como std::sort() std::find() e std::for_each() mais flexíveis. Você pode passar iteradores em vez do contêiner real.

Exemplo

C++
#include    using namespace std; int main() {  vector<int> vec = {30 10 40   10 50};  multiset<int> ms = {10 30 10   20 40 10};  // Using the std::count() algorithm to count  // the number of occurences of 10 in vector  // and multiset using iterator  cout << '10s in Vector: '   << count(vec.begin()  vec.end() 10) << endl;  cout << '10s in Multiset: '   << count(ms.begin()  ms.end() 10);  return 0; } 

Saída
10s in Vector: 2 10s in Multiset: 3

Aplicações Adicionais de Iteradores

Existem mais aplicações de iteradores STL:

  • Cálculo de distância: O uso de iteradores std::distance() ajuda a calcular o número de elementos entre duas posições em um contêiner.
  • Iteração de fluxo: Os iteradores de fluxo permitem tratar fluxos de entrada/saída como contêineres, facilitando a leitura e gravação em fluxos usando algoritmos STL.
  • Mover semântica em algoritmos STL: Move iterators introduz a semântica de movimento em algoritmos STL que ajuda a aumentar o desempenho e a eficiência, evitando cópias desnecessárias. Os dados serão movidos de acordo com as regras de semântica de movimentação.
  • Iteradores personalizados para estruturas de dados: Iteradores personalizados podem ser implementados para estruturas de dados não STL, como árvores ou gráficos, para fornecer suporte para algoritmos STL e muitos outros recursos. Podemos precisar seguir alguns conjuntos de regras e convenções para fornecer incrementos, decrementos e outras operações adequadas.