C++: Fundamentos de Contêineres STL

Nas lições anteriores, aprendemos sobre templates — fazendo com que funções e classes suportem qualquer tipo.

Mas em projetos reais, você não precisa escrever seus próprios contêineres (como arrays dinâmicos ou listas encadeadas).

A Biblioteca de Templates Padrão (STL) do C++ já fornece contêineres prontos — basta usá-los diretamente!


1. O que é a STL?

A STL (Standard Template Library) é parte da biblioteca padrão do C++, contendo:

Componente Finalidade Exemplos
Contêineres Armazenar dados std::vector, std::array
Iteradores Percorrer contêineres begin(), end()
Algoritmos Manipular dados std::sort, std::find
Objetos de função Lógica de comparação personalizada std::less, std::greater

💡 Ponto-chave: A STL é implementada com templates, então suporta qualquer tipo.



2. vector (Mais Usado)

(1) 2.1 O que é vector?

std::vector é um array dinâmico — seu tamanho pode crescer automaticamente.

Comparação Array Comum vector
Tamanho Fixo Dinâmico
Memória Stack ou heap Heap
Acessar elementos arr[i] vec[i] ou vec.at(i)
Recomendação ⭐⭐ ⭐⭐⭐⭐⭐

▶ Exemplo 1: Uso Básico de vector (Dificuldade ⭐)

CPP
#include <iostream>
#include <vector>

int main() {
 // Create a vector storing ints
 std::vector<int> vec = {1, 2, 3, 4, 5};
 
 // Access elements
 std::cout << "First element: " << vec[0] << std::endl;
 std::cout << "Second element: " << vec.at(1) << std::endl;
 
 // Modify elements
 vec[0] = 100;
 
 // Get size
 std::cout << "Size: " << vec.size() << std::endl;
 
 return 0;
}
▶ Experimente

Saída:

TEXT 📖 Somente leitura
First element: 1
Second element: 2
Size: 5

💡 Dica: vec.at(i) realiza verificação de limites e lança uma exceção se fora dos limites; vec[i] não verifica, e é mais eficiente.


(2) 2.2 Adicionando e Removendo Elementos

CPP
#include <iostream>
#include <vector>

int main() {
 std::vector<int> vec;
 
 // Add elements to the end
 vec.push_back(10);
 vec.push_back(20);
 vec.push_back(30);
 
 // Remove the last element
 vec.pop_back();
 
 // Insert element at a specified position
 vec.insert(vec.begin() + 1, 15); // Insert 15 at the second position
 
 // Remove element at a specified position
 vec.erase(vec.begin() + 1); // Remove the second element
 
 return 0;
}

(3) 2.3 Percorrendo um vector

Método 1: Percorrimento por subscrito (mais comum)

CPP
#include <iostream>
#include <vector>

int main() {
 std::vector<int> vec = {1, 2, 3, 4, 5};
 
 for (size_t i = 0; i < vec.size(); i++) {
 std::cout << vec[i] << " ";
 }
 std::cout << std::endl;
 
 return 0;
}

Método 2: for baseado em intervalo (C++11, recomendado)

CPP
#include <iostream>
#include <vector>

int main() {
 std::vector<int> vec = {1, 2, 3, 4, 5};
 
 for (int x : vec) {
 std::cout << x << " ";
 }
 std::cout << std::endl;
 
 return 0;
}

Método 3: Iteradores (abordado mais tarde)

CPP
#include <iostream>
#include <vector>

int main() {
 std::vector<int> vec = {1, 2, 3, 4, 5};
 
 for (auto it = vec.begin(); it != vec.end(); ++it) {
 std::cout << *it << " ";
 }
 std::cout << std::endl;
 
 return 0;
}

💡 Recomendação: Prefira for baseado em intervalo (C++11) — é o mais conciso.



3. array (Array de Tamanho Fixo)

(1) 3.1 O que é array?

std::array é um array de tamanho fixo, mas mais seguro que um array comum.

Comparação Array Comum array
Tamanho Você precisa saber Obtenha com size()
Decompõe para ponteiro? Sim Não
Recomendação ⭐⭐ ⭐⭐⭐⭐

▶ Exemplo 2: Uso Básico de array (Dificuldade ⭐)

CPP
#include <iostream>
#include <array>

int main() {
 // Create an array storing 5 ints
 std::array<int, 5> arr = {1, 2, 3, 4, 5};
 
 // Access elements
 std::cout << "First element: " << arr[0] << std::endl;
 
 // Get size
 std::cout << "Size: " << arr.size() << std::endl;
 
 return 0;
}
▶ Experimente

Saída:

TEXT 📖 Somente leitura
First element: 1
Size: 5

💡 Ponto-chave: O tamanho de std::array é determinado em tempo de compilação e não pode ser alterado.



4. deque (Fila de Duas Pontas)

(1) 4.1 O que é deque?

std::deque é uma fila de duas pontas — você pode adicionar/remover elementos rapidamente em ambas as extremidades.

Operação vector deque
Adicionar no final O(1) O(1)
Adicionar no início O(n) O(1)
Acesso aleatório O(1) O(1)

▶ Exemplo 3: Uso Básico de deque (Dificuldade ⭐⭐)

CPP
#include <iostream>
#include <deque>

int main() {
 std::deque<int> dq;
 
 // Add at end
 dq.push_back(10);
 dq.push_back(20);
 
 // Add at front
 dq.push_front(5);
 dq.push_front(1);
 
 // dq is now: 1, 5, 10, 20
 
 for (int x : dq) {
 std::cout << x << " ";
 }
 std::cout << std::endl;
 
 return 0;
}
▶ Experimente

Saída:

TEXT 📖 Somente leitura
1 5 10 20


5. list (Lista Duplamente Encadeada)

(1) 5.1 O que é list?

std::list é uma lista duplamente encadeada — cada elemento armazena os endereços do elemento anterior e do próximo.

Comparação vector list
Acesso aleatório O(1) ❌ Não suportado
Inserir/deletar no meio O(n) O(1)
Uso de memória Pequeno Grande (dois ponteiros extras por elemento)

▶ Exemplo 4: Uso Básico de list (Dificuldade ⭐⭐)

CPP
#include <iostream>
#include <list>

int main() {
 std::list<int> lst = {1, 2, 3, 4, 5};
 
 // Add at front
 lst.push_front(0);
 
 // Add at end
 lst.push_back(6);
 
 // Remove elements with value 3
 lst.remove(3);
 
 for (int x : lst) {
 std::cout << x << " ";
 }
 std::cout << std::endl;
 
 return 0;
}
▶ Experimente

Saída:

TEXT 📖 Somente leitura
0 1 2 4 5 6


6. forward_list (Lista Simplesmente Encadeada)

(1) 6.1 O que é forward_list?

std::forward_list é uma lista simplesmente encadeada — cada elemento armazena apenas o endereço do próximo elemento.

Comparação list forward_list
Uso de memória Maior Menor
Pode percorrer para trás?
Recomendação ⭐⭐⭐⭐ ⭐⭐ (para cenários específicos)

💡 Conselho: A menos que você tenha certeza de que só precisa percorrer para frente, use std::list.



7. Guia de Seleção de Contêineres

Cenário Contêiner Recomendado
Precisa de tamanho dinâmico std::vector
Tamanho fixo, deseja compatibilidade com C std::array
Precisa de adição/remoção rápida no início std::deque
Inserção/remoção frequente no meio std::list
Só precisa percorrer para frente e economizar memória std::forward_list

💡 Regra de ouro: Prefira std::vector a menos que tenha um motivo claro para usar outro.



8. Prática: Array Dinâmico com vector (Dificuldade ⭐⭐)

CPP
#include <iostream>
#include <vector>
#include <string>

struct Student {
 std::string name;
 int age;
 double score;
};

int main() {
 std::vector<Student> students;
 
 // Add students
 students.push_back({"Alice", 20, 92.5});
 students.push_back({"Bob", 21, 88.0});
 students.push_back({"Charlie", 19, 95.0});
 
 // Traverse and output
 for (const auto& s : students) {
 std::cout << "Name: " << s.name 
 << ", Age: " << s.age 
 << ", Score: " << s.score << std::endl;
 }
 
 return 0;
}

❓ Perguntas Frequentes

P: Qual a diferença entre vector e array? R:> - vector tem tamanho dinâmico, armazenado no heap > - array tem tamanho fixo, armazenado na stack > > Conselho de seleção: Se o tamanho é incerto, use vector; se o tamanho é fixo e pequeno, use array. P: Por que o for baseado em intervalo é recomendado para percorrer vector? R: Porque é mais conciso e menos propenso a erros nas condições do loop. > > // Traditional for (easy to get conditions wrong) > for (size_t i = 0; i < vec.size(); i++) { ... } > > // Range-based for (concise, less error-prone) > for (int x : vec) { ... } > P: Qual é mais rápido — list ou vector? R: Depende do cenário: > - Se você precisa de acesso aleatório (vec[100]), vector é mais rápido > - Se você precisa de inserção/remoção frequente no meio, list é mais rápido


P: Qual é a coisa mais importante sobre contêineres STL? R: Entenda os conceitos centrais primeiro, depois reforce-os através de exemplos práticos.

📖 Resumo


📝 Exercícios

  1. Básico (Dificuldade ⭐): Use std::vector<int> para armazenar 5 inteiros, percorra e exiba-os.

  2. Intermediário (Dificuldade ⭐⭐): Use std::vector<std::string> para armazenar 3 strings, permita que o usuário as insira, depois exiba.

  3. Desafio (Dificuldade ⭐⭐⭐): Use std::deque para implementar "detecção de palíndromo":

  4. Compare de ambas as extremidades em direção ao meio; se todos os caracteres correspondentes forem iguais, é um palíndromo

  5. Exemplo: "racecar" é um palíndromo, "hello" não é


9. 🚀 Próximos Passos

Agora que você aprendeu os fundamentos de contêineres STL, a seguir vamos estudar Algoritmos STL (lição 35) — usando os algoritmos fornecidos pela biblioteca padrão para manipular contêineres, para que você não precise escrever sua própria ordenação, busca...

Web-Tutorial.com

Equipe Técnica Web-Tutorial

Uma plataforma de tutoriais mantida por diversos desenvolvedores. Cada tutorial é escrito e revisado por profissionais da área correspondente. Trabalhamos para manter nosso conteúdo preciso e confiável — se encontrar algum problema, avise-nos.

100%