Vistas, Iteradores e Percorríveis
Igor Machado Coelho
03/11/2026
São requisitos para essa aula o conhecimento de:
concept) em C++, vistos nas aulas
de Pilhas e FilasAté agora, nossos TADs (Pilha, Fila, Conjunto) guardam seus elementos: cada um é dono dos seus dados.
Mas como olhar para os elementos de uma estrutura, um por um, sem copiá-los e sem conhecer como ela foi implementada?
Nesta aula, definiremos três componentes básicos, que usaremos em todas as próximas estruturas:
Eles existem, com outros nomes, em todas as linguagens modernas!
Uma Vista (do inglês View) é um TAD que referencia um valor guardado em outro lugar (a origem), com três propriedades: não-posse: alterações na origem são percebidas pela vista; leve: custo constante O(1); validade: dura enquanto a origem existir.
Desafio: por que origem é do tipo
const int* e não int*?
Uma Vista Mutável é uma Vista que também possui
altera(v), que modifica o valor na
origem.
template <typename V>
concept VistaMutavelTAD = VistaTAD<V> &&
requires(V v, typename V::Tipo t) {
{ v.altera(t) }; // escrita na origem
};
struct VistaMutavelInt {
using Tipo = int; // tipo associado
Tipo* origem;
Tipo le() { return *origem; }
void altera(Tipo v) { *origem = v; }
};
static_assert(VistaMutavelTAD<VistaMutavelInt>);Desafio: VistaMutavelInt satisfaz
VistaTAD? E VistaInt satisfaz
VistaMutavelTAD?
Uma Vista de Vetor é uma vista de vários
elementos consecutivos, lidos pela posição i. A Vista
Mutável de Vetor também altera o elemento, na
origem.
template <typename V, typename T>
concept VistaVetorTAD = requires(V v, int i) {
{ v.tamanho() } -> std::same_as<int>;
{ v.le(i) } -> std::same_as<T>;
};
template <typename V, typename T>
concept VistaMutavelVetorTAD =
VistaVetorTAD<V, T> &&
requires(V v, int i, T t) {
{ v.altera(i, t) };
}; // le e altera: pre(0 <= i < tamanho())
// o SpanInt da introdução já serve!
static_assert(VistaMutavelVetorTAD<SpanInt, int>);Importante: a vista é passada por
valor (é leve!), mas altera muda o vetor original.
É assim que receberemos vetores nos algoritmos de ordenação.
Um Iterador (do inglês Iterator) é uma
Vista do elemento atual que pode se
mover: além de le(), possui proximo()
e terminou().
template <typename It, typename T>
concept IteradorTAD = VistaTAD<It> &&
std::same_as<typename It::Tipo, T> &&
requires(It it) {
{ it.terminou() }; // fim da origem?
{ it.proximo() }; // avança
};
struct IteradorVetorInt {
using Tipo = int;
const Tipo* atual; // posição atual
const Tipo* fim; // após o último
Tipo le() { return *atual; }
bool terminou() { return atual == fim; }
void proximo() { atual++; }
};
static_assert(IteradorTAD<IteradorVetorInt, int>);Desafio: o que acontece se chamarmos
le() quando terminou() é verdadeiro?
Um Percorrível (do inglês Iterable ou
Range) é um TAD com uma única operação:
iterador(), que retorna um Iterador
posicionado no primeiro elemento e permite visitar os demais.
// Exemplo de busca no trio
auto buscaTrio(auto it, int x) {
while(!it.terminou() && it.le() != x)
it.proximo();
return it; // terminou() se não achou
}
// Exemplo de uso
TrioInt t{.dados = {10, 20, 30}};
println("{}",
buscaTrio(t.iterador(), 20).le());
println("{}",
buscaTrio(t.iterador(), 99).terminou());Desafio: qual o custo de busca? Seria
possível fazer melhor?
Os mesmos conceitos aparecem, com outros nomes, nas linguagens modernas:
| Curso | C++ | Java | Python | Posse? |
|---|---|---|---|---|
| Vista | std::string_view, std::span |
- | memoryview |
não |
| Iterador | iteradores (*, ++, fim) |
Iterator |
iterador (next) |
não |
| Percorrível | range (begin/end) |
Iterable |
iterable (iter) |
pode ter |
Note que um Percorrível pode ser dono dos elementos
(um std::vector é um range), mas Vistas e
Iteradores nunca são: são leves, e por isso podem ser
passados por valor.
Observação: como nossos TADs não são
copiáveis, algoritmos genéricos (como buscaTrio) recebem o
iterador, e não o Percorrível!
Implemente um Iterador Mutável.
template <typename It, typename T>
concept IteradorMutavelTAD = IteradorTAD<It, T> && VistaMutavelTAD<It>;Quais métodos ele teria? Para que serviria?
Outra reflexão: Vistas são TAD muito simples e não carregam recursos
dinâmicos (non-owning), portanto não terão
métodos cria() e libera() nesse curso.
A validade da Vista pode ser verificada pelo compilador (Clang 23+)
com construtor cujo parâmetro seja anotado com
lifetimebound, ligando a vida da Vista à vida da
origem.
#if __has_cpp_attribute(clang::lifetimebound)
#define LFTM [[clang::lifetimebound]]
#else
#define LFTM // outros compiladores: ignora
#endif
struct VistaVerificavelInt {
using Tipo = int;
const Tipo* origem;
VistaVerificavelInt(const Tipo* x LFTM)
: origem(x) {}
Tipo le() { return *origem; }
};
static_assert(VistaTAD<VistaVerificavelInt>);// Exemplo de uso (com erro!)
int z = 0;
VistaVerificavelInt y{&z};
{
int x = 10;
y = VistaVerificavelInt(&x);
} // x morre aqui...
println("{}", y.le()); // ... y ainda usa$ clang++ -std=c++20 -Wlifetime-safety ...
warning: local variable ‘x’ does not
live long enough
note: local variable ‘x’ is destroyed here
note: later used here
Desafio: e com a VistaInt (sem
construtor), o compilador avisa? Por quê?
Próxima aula: o Saco, nosso primeiro TAD Percorrível, implementado com listas encadeadas e vetores!
Além da bibliografia do curso, recomendamos para esse tópico:
Bibliografia Adicional:
Em especial, agradeço aos colegas que elaboraram bons materiais, como o prof. Fabiano Oliveira (IME-UERJ), e o prof. Jayme Szwarcfiter cujos conceitos formam o cerne desses slides.
Estendo os agradecimentos aos demais colegas que colaboraram com a elaboração do material do curso de Pesquisa Operacional, que abriu caminho para verificação prática dessa tecnologia de slides.
Esse material de curso só é possível graças aos inúmeros projetos de código-aberto que são necessários a ele, incluindo:
Agradecimento especial a empresas que suportam projetos livres envolvidos nesse curso:
Esses slides foram escritos utilizando pandoc, segundo o tutorial ilectures:
Exceto expressamente mencionado (com as devidas ressalvas ao material cedido por colegas), a licença será Creative Commons.
Licença: CC-BY 4.0 2020
Igor Machado Coelho