Pular para conteúdo

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:

  1. 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.
  2. 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.
  3. Semanas 5–7: exceções e templates. Nessa ordem: exceções para ler código alheio, templates para entender a biblioteca padrão.
  4. 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.