Próximos passos em C++¶
Primeiro: o que você já sabe fazer¶
Antes da lista do que falta, um balanço honesto — porque é fácil terminar um curso olhando só para o tamanho do que ficou de fora.
Em 16 semanas você saiu de "sei lógica de programação em C" e chegou a escrever
C++ que: passa parâmetros por referência e por const& sem copiar o que não
precisa; usa vector, map e set em vez de gerenciar arrays e buscas na mão;
lê e grava arquivos; resolve problemas com <algorithm> e lambdas em vez de
laços escritos à mão (e escreveu esses laços antes, para saber o que a biblioteca
está fazendo); modela domínios com classes que protegem seus invariantes; entende
ciclo de vida de objeto, RAII e por que a regra do zero elimina uma classe
inteira de bugs; usa polimorfismo com virtual; separa código em .h/.cpp; e
implementou fila, pilha e lista encadeada sem vazar memória. Ah, e rodou C++
orientado a objetos num microcontrolador.
Isso já é uma base profissional. O que segue são caminhos, não lacunas.
Ninguém aprende tudo isso de uma vez — e ninguém precisa
C++ é uma linguagem grande, e programadores experientes convivem tranquilamente com cantos dela que nunca usaram. Escolha uma frente e vá fundo nela; voltar depois para as outras é sempre mais fácil do que tentar três ao mesmo tempo.
Frente 1 — A linguagem que ficou de fora¶
Cada item diz que problema resolve e onde o curso encostou nele.
std::optional<T> — comece por aqui. É o assunto mais próximo do que você já
sabe, e o que mais melhora código do dia a dia. O curso resolveu "a função pode
não ter resposta" de duas formas, no capítulo 3:
um valor impossível (-1 para índice) ou bool de retorno com o resultado saindo
por um parâmetro de referência. As duas funcionam, e as duas têm defeito. O valor
impossível só existe por sorte do problema — some no dia em que a função devolve
um valor do domínio, em que -1 é uma resposta legítima. E o parâmetro de saída
obriga quem chama a declarar a variável antes, torna a assinatura mais longa e não
impede ninguém de ler a variável ignorando o bool.
std::optional<T> é o tipo que diz "ou tem um T, ou não tem nada" sem nenhuma
das duas concessões:
#include <optional>
std::optional<double> divide(double a, double b) {
if (b == 0.0) {
return std::nullopt; // "nao tem resultado", sem ambiguidade
}
return a / b; // o double vira um optional com valor
}
if (auto r = divide(9.0, 3.0)) {
std::cout << *r << "\n"; // 3
}
std::cout << divide(1.0, 0.0).value_or(0.0) << "\n"; // 0
O resultado vem no retorno, onde ele deveria estar; não existe valor mágico a
combinar; e ler o valor sem checar é um erro que se percebe (value() num
optional vazio aborta o programa, em vez de devolver lixo silenciosamente).
Reescreva com optional duas ou três funções das listas 03 e 05 — busca_posicao,
moda, k_esimo_menor — e a diferença aparece na hora. Depois veja
std::expected (C++23), que é o mesmo com um motivo de falha anexado.
try/catch e exceções de verdade — o capítulo 10
declara explicitamente que o assunto ficou fora do escopo, e usou apenas a
garantia de que destrutores rodam durante uma exceção. Falta o outro lado:
como lançar um erro (throw), como tratá-lo, e por que optional (capítulo 3)
é melhor que exceção para "não encontrei" e pior para "não consegui continuar".
Comece por aqui: é o primeiro assunto que você vai encontrar em código alheio.
Templates — você usou vector<int>, map<string, int>, optional<Aluno>
durante metade do curso sem nunca escrever um template seu. Aprender a escrever
um é entender como a biblioteca padrão inteira é construída: uma função ou classe
parametrizada por tipo, resolvida em tempo de compilação, sem custo em tempo de
execução. É a maior mudança de patamar da lista.
Semântica de movimento e a regra dos 5 — o std::move do capítulo 10
apareceu como "autoriza roubar o conteúdo", e ficou nisso. A explicação completa
envolve referências rvalue (T&&), construtor de movimento e operador de
atribuição por movimento — os dois que, somados aos três da regra dos 3, dão a
regra dos 5. É o que permite devolver um vector de uma função sem copiar nada.
Polimorfismo além do básico — herança múltipla e interfaces, dynamic_cast,
e por que "prefira composição a herança" é conselho tão repetido. Continuação
direta do capítulo 11, que já
cobriu o essencial: virtual, override, classe abstrata e destrutor virtual.
std::array e constexpr — o array de tamanho fixo (sem alocação dinâmica,
diferente do vector) e o cálculo feito em tempo de compilação. Importa
especialmente para embarcados, onde alocar no heap é caro ou proibido — a Unidade
7 conviveu com essa restrição sem nomeá-la.
C++20: ranges, concepts e std::format — o curso é C++17. As três novidades
que mais mudam o dia a dia: ranges deixam escrever
v | filter(...) | transform(...) em vez de iteradores soltos (compare com o
capítulo 8); concepts dão mensagens de erro legíveis para templates; e
std::format substitui a concatenação com << por algo parecido com o printf,
só que seguro.
Threads e concorrência — std::thread, std::mutex, e o lock_guard, que é
RAII aplicado a travas (adquire no construtor, libera no destrutor — exatamente o
padrão do capítulo 10, com um recurso diferente). Assunto difícil e fácil de
errar; deixe para depois das outras frentes.
Frente 2 — O ecossistema profissional¶
Saber a linguagem é metade do trabalho; a outra metade é o ferramental em torno dela. Nesta frente o retorno por hora de estudo é o mais alto da página.
CMake — o g++ na mão e o Makefile deste repositório funcionam para 20
arquivos; nenhum projeto real é compilado assim. CMake é o padrão de fato para
descrever como um projeto C++ se compila, em qualquer sistema operacional.
Aprenda antes de qualquer item da Frente 1.
git — controle de versão. Se você ainda não usa, comece hoje, e não só para C++: é a ferramenta que separa "tenho uma pasta com trabalho4_final_v2" de trabalhar em equipe.
Testes automatizados: Catch2 ou GoogleTest — as listas deste curso são
corrigidas por assert(), que é a versão de brinquedo disso. Um framework de
teste de verdade roda centenas de casos, diz qual falhou e por quê, e não para no
primeiro erro. Escrever teste é o hábito que mais melhora código C++.
Sanitizers: ASan e UBSan — recompile com -fsanitize=address,undefined e o
programa passa a acusar em tempo de execução, com número de linha, o double
free e o acesso fora dos limites do capítulo 10
— bugs que hoje só se manifestam como "crash esquisito". São uma flag de
compilação: custa cinco minutos aprender e economiza tardes inteiras.
Um depurador (gdb, lldb, ou o do seu editor) — parar o programa numa linha
e inspecionar as variáveis, em vez de espalhar std::cout. Aprenda quatro
comandos (break, run, print, next) e já vale.
clang-format e clang-tidy — o primeiro formata seu código segundo um
padrão, encerrando discussões de estilo; o segundo é um analisador que aponta
problemas reais antes de você rodar (inclusive várias violações das Core
Guidelines citadas no apêndice de referências).
Gerenciadores de pacote: vcpkg ou Conan — como usar bibliotecas de terceiros sem baixar código-fonte na mão. Deixe para quando um projeto seu precisar de uma biblioteca externa.
Frente 3 — Trilhas de aplicação¶
Onde aplicar tudo isso. Em todas elas, o que você já tem (classes, RAII,
containers, <algorithm>) é reaproveitado inteiro.
Embarcados — continuação direta da Unidade 7. Saia do Wokwi para hardware real (ESP32, STM32, Raspberry Pi Pico), e estude o que muda quando não há sistema operacional: sem alocação dinâmica, sem exceções, com atenção a cada byte de RAM. A arquitetura testável do capítulo 15 é a prática central da área.
Jogos — a área que mais usa C++ na indústria. Comece por SDL2 ou SFML para 2D (ambas bibliotecas pequenas, boas para aprender), e Unreal Engine se o interesse for a indústria. Herança, polimorfismo e ciclo de vida de objeto são usados o tempo todo.
Aplicações de desktop com Qt — interface gráfica multiplataforma, com uma biblioteca imensa e bem documentada. Qt tem convenções próprias (sinais e slots), mas o fundamento é o C++ com classes que você aprendeu.
Programação competitiva — Codeforces, AtCoder, Beecrowd. C++ é a linguagem
dominante lá por causa da STL: vector, map, sort, lower_bound — tudo o
que você já viu na Unidade 2 e no capítulo 8. É a forma mais barata de treinar
algoritmos e ganhar velocidade de codificação.
Computação de alto desempenho — onde C++ é escolhido justamente por permitir
controle fino de memória e custo zero de abstração: simulação científica,
finanças, processamento de imagem, bancos de dados. Requer entender cache,
alinhamento e perfilamento (perf, valgrind --tool=callgrind).
Uma ordem sugerida para os próximos três meses¶
Não é a única possível, mas é uma que funciona — cada passo se apoia no anterior:
- Semanas 1–2: git e CMake. Coloque um projeto seu num repositório que compila com CMake. Sem isso, todo o resto fica preso ao ambiente do curso.
- Semanas 3–4: um framework de teste. Reescreva os exercícios de uma lista
deste curso com Catch2 no lugar dos
assert(), e ligue os sanitizers. - Semanas 5–7: exceções e templates. Nessa ordem: exceções para ler código alheio, templates para entender a biblioteca padrão.
- Semanas 8–12: um projeto seu, de ponta a ponta, na trilha da Frente 3 que mais te interessar. Maior do que o projeto final do curso, com testes e commits regulares.
Estude o resto da Frente 1 quando um problema concreto pedir — é assim que esses tópicos ficam, em vez de virarem uma lista de coisas que você "já leu sobre".
E onde estudar cada item: veja o apêndice de referências.