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++:
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çar | Retorna um iterador para o primeiro elemento do contêiner fornecido. | começar ( recipiente ) |
| std::fim | Retorna um iterador para o elemento após o último elemento do contêiner fornecido. | fim ( recipiente ) |
| std::rbegin | Retorna um iterador reverso para o último elemento do contêiner fornecido. | começar ( recipiente ) |
| std::rend | Retorna 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.