Iteradores
Parte da seção Programação Orientada a Objetos do Journey de C++ da Coddy — lição 72 de 104.
Iteradores são objetos que atuam como uma ponte entre contêineres e algoritmos. Eles fornecem uma maneira uniforme de acessar elementos em qualquer contêiner, independentemente de como esse contêiner armazena seus dados internamente. Pense em um iterador como um ponteiro generalizado que sabe como percorrer um contêiner.
Todo contêiner STL fornece os métodos begin() e end(). O iterador begin() aponta para o primeiro elemento, enquanto end() aponta para uma posição após o último elemento - uma sentinela que marca onde parar:
#include <vector>
#include <iostream>
int main() {
std::vector<int> nums = {10, 20, 30};
for (std::vector<int>::iterator it = nums.begin(); it != nums.end(); ++it) {
std::cout << *it << " "; // Desreferenciar para obter o valor
}
// Saída: 10 20 30
}A palavra-chave auto simplifica significativamente as declarações de iteradores:
for (auto it = nums.begin(); it != nums.end(); ++it) {
*it *= 2; // Modifica elementos através do iterador
}
// nums agora é {20, 40, 60}Iteradores vêm em diferentes categorias com base em suas capacidades. Iteradores de acesso aleatório (como aqueles de vector) suportam operações aritméticas como it + 3 ou it1 - it2.
Iteradores bidirecionais (de list, map) podem se mover para frente e para trás com ++ e --. Iteradores forward podem se mover apenas em uma direção.
Para percorrer em ordem inversa, use rbegin() e rend():
for (auto rit = nums.rbegin(); rit != nums.rend(); ++rit) {
std::cout << *rit << " "; // Imprime na ordem inversa
}Desafio
FácilVamos construir um sistema de rastreamento de inventário que utiliza iteradores para percorrer e manipular coleções de itens. Você praticará o uso de diferentes tipos de iteradores para navegar pelos dados de várias maneiras.
Você organizará seu código em dois arquivos:
Inventory.h: Defina uma classeInventoryque gerencia uma coleção de quantidades de itens armazenadas em umstd::vector<int>.Sua classe deve fornecer estes métodos:
addItem(int quantity)— adiciona uma quantidade de item ao inventárioprintForward()— usa iteradores combegin()eend()para imprimir todas as quantidades separadas por espaços, seguidas por uma nova linhaprintReverse()— usa iteradores reversos comrbegin()erend()para imprimir todas as quantidades em ordem reversa, separadas por espaços, seguidas por uma nova linhadoubleAll()— usa iteradores para percorrer o vetor e dobrar cada quantidade no localgetTotal()— usa iteradores para calcular e retornar a soma de todas as quantidades
Use a palavra-chave
autopara suas declarações de iteradores para manter o código limpo.main.cpp: Leia quatro entradas inteiras (cada uma em uma linha separada) representando quantidades de itens.Crie um
Inventorye adicione todas as quatro quantidades. Em seguida, demonstre o uso de iteradores:- Imprimindo
Forward:seguido pela chamada deprintForward() - Imprimindo
Reverse:seguido pela chamada deprintReverse() - Imprimindo
Total: <sum>usandogetTotal() - Chamando
doubleAll()para modificar as quantidades - Imprimindo
After doubling:seguido pela chamada deprintForward() - Imprimindo
New total: <sum>usandogetTotal()
- Imprimindo
Por exemplo, com as entradas 10, 25, 15, e 30:
Forward: 10 25 15 30
Reverse: 30 15 25 10
Total: 80
After doubling: 20 50 30 60
New total: 160Este desafio permite que você pratique tanto a leitura de elementos através de iteradores (para impressão e soma) quanto a modificação de elementos através de iteradores (para dobrar). Você também verá como os iteradores reversos tornam a travessia para trás direta, sem qualquer manipulação de índice.
Folha de consulta
Iteradores são objetos que fornecem uma maneira uniforme de acessar elementos em contêineres. Eles agem como ponteiros generalizados que sabem como se mover através de um contêiner.
Todo contêiner STL fornece os métodos begin() e end(). O iterador begin() aponta para o primeiro elemento, enquanto end() aponta para uma posição após o último elemento:
std::vector<int> nums = {10, 20, 30};
for (std::vector<int>::iterator it = nums.begin(); it != nums.end(); ++it) {
std::cout << *it << " "; // Desreferencie para obter o valor
}Use a palavra-chave auto para simplificar as declarações de iteradores:
for (auto it = nums.begin(); it != nums.end(); ++it) {
*it *= 2; // Modifique elementos através do iterador
}Categorias de iteradores baseadas em capacidades:
- Iteradores de acesso aleatório (ex:
vector) suportam operações aritméticas comoit + 3ouit1 - it2 - Iteradores bidirecionais (ex:
list,map) podem se mover para frente e para trás com++e-- - Iteradores de avanço (Forward iterators) só podem se mover em uma direção
Para travessia reversa, use rbegin() e rend():
for (auto rit = nums.rbegin(); rit != nums.rend(); ++rit) {
std::cout << *rit << " "; // Imprime em ordem reversa
}Experimente você mesmo
#include <iostream>
#include "Inventory.h"
using namespace std;
int main() {
// Leia quatro entradas inteiras
int q1, q2, q3, q4;
cin >> q1;
cin >> q2;
cin >> q3;
cin >> q4;
// TODO: Crie um objeto Inventory
// TODO: Adicione todas as quatro quantidades ao inventário
// TODO: Imprima "Forward: " e então chame printForward()
// TODO: Imprima "Reverse: " e então chame printReverse()
// TODO: Imprima "Total: " seguido pelo resultado de getTotal()
// TODO: Chame doubleAll() para modificar as quantidades
// TODO: Imprima "After doubling: " e então chame printForward()
// TODO: Imprima "New total: " seguido pelo resultado de getTotal()
return 0;
}
Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.
Todas as lições de Programação Orientada a Objetos
1Fundamentos de OOP
Arquivos ExternosBuild e Compilação em C++Arquivos Header e SourceNamespaces e EscopoIntrodução a OOP em C++Classes vs ObjetosO Ponteiro 'this'Métodos (Funções Membro)Atributos (Membros de Dados)Básico de Ctors e DtorsRecapitulação - Calculadora Simples4Propriedades de Classe
Membros de Instância vs EstáticosGetters e SettersFunções de Membro ConstPalavra-chave MutableMétodos e Variáveis EstáticosFunções e Classes FriendRecapitulação - Gerenciador de Conta Bancária7Herança
Herança BásicaNíveis de Acesso na HerançaOrdem de Chamada de Ctor e DtorSobrescrita de MétodosFunções Virtuais e VTableHerança MúltiplaHerança VirtualRecapitulação - Hierarquia de Funcionários2Gerenciamento de Memória
Memória Stack vs HeapPonteiros e ReferênciasMemória Dinâmica (new/delete)Smart Pointers em C++RAII em C++Recapitulação - Gerenciador de Array Dinâmico5Encapsulamento
Especificadores de Acesso em C++Especificadores de Acesso em DetalhesOcultação de InformaçãoStruct vs ClassClasses Aninhadas e InternasRecapitulação - Sistema de Registros de Alunos8Polimorfismo
Polimorfismo de Compilação vs Tempo de ExecuçãoSobrecarga de FunçõesFunções Virtuais RevisitadasFunções Virtuais PurasClasses AbstratasDesign de Interfaces em C++Dynamic Casting e RTTIRecapitulação - Calculadora de Formas3Construtores e Destrutores
Construtor PadrãoConstrutor ParametrizadoConstrutor de CópiaConstrutor de MovimentaçãoListas de Inicialização do ConstrutorConstrutores DelegadosMergulho Profundo em DestrutoresRegra dos Três / Cinco / ZeroRecapitulação - Classe String6Sobrecarga de Operadores
Introdução à Sobrecarga de OperadoresSobrecarga de Operadores AritméticosSobrecarga de Operadores de ComparaçãoOperadores de StreamSobrecarga do Operador de AtribuiçãoSobrecarga dos Operadores [] e ()Operadores de Conversão de TipoRecapitulação - Classe Matrix9Templates
Templates de FunçãoTemplates de ClasseEspecialização de TemplatesTemplates VariádicosFundamentos de SFINAE e Type TraitsRecapitulação - Container Genérico