C++ Moderno
Guia para escrever C++ moderno utilizando expressões de C++20, C++23 e C++26. Foca em padrões que eliminam classes de vulnerabilidade e reduzem código boilerplate, com ênfase em segurança da Trail of Bits.
Quando Usar Esta Skill
- Escrevendo novas funções, classes ou bibliotecas em C++
- Modernizando código C++ existente (padrões anteriores a C++20)
- Escolhendo entre abordagens legadas e modernas
- Trabalhando com C++ crítico para segurança ou segurança funcional
- Revisando código C++ para adoção de expressões modernas
Quando NÃO Usar Esta Skill
- Usuário exige explicitamente padrão antigo: Respeite restrições (embedded, ABI legada)
- Código C puro: Esta skill é específica para C++
- Questões de sistema de build: Configuração de CMake, Meson, Bazel está fora do escopo
- Projetos não C++: Codebases mistas onde C++ não é a linguagem principal
Anti-Padrões a Evitar
| Evitar | Usar em vez disso | Por quê |
|---|---|---|
new/delete | std::make_unique, std::make_shared | Elimina vazamentos, double-free |
| Ponteiros brutos proprietários | std::unique_ptr, std::shared_ptr | Semântica de propriedade RAII |
Arrays C (int arr[N]) | std::array<int, N> | Consciente de limites, semântica de valor |
| Parâmetros ponteiro + tamanho | std::span<T> | Não proprietário, verificável por limites |
printf / sprintf | std::format, std::print | Type-safe, sem estouro de buffer |
Casts estilo C (int)x | static_cast<int>(x) | Intenção explícita, auditável |
Constantes #define | Variáveis constexpr | Escopo definido, tipadas, depuráveis |
SFINAE / enable_if | Conceitos + requires | Restrições e erros legíveis |
| Códigos de erro + parâmetros de saída | std::expected<T, E> | Erros componíveis e type-safe |
union | std::variant | Type-safe, sem UB silencioso |
mutex.lock()/unlock() brutos | std::scoped_lock | Seguro contra exceções, sem deadlocks |
std::thread | std::jthread | Auto-join, suporte a token de parada |
Macro assert() | contract_assert (C++26) | Visível para ferramentas, configurável |
| CRTP manual | Deducing this (C++23) | Mais simples, sem boilerplate de template |
| Geração de código com macros | Reflexão (C++26) | Custo zero, componível |
Consulte anti-patterns.md para a tabela completa (30+ padrões).
Árvore de Decisão
O que você está fazendo?
|
+-- Escrevendo novo código C++?
| +-- Use expressões modernas por padrão (C++20/23)
| +-- Escolha o padrão mais recente que seu compilador suporta
| +-- Veja as Camadas de Funcionalidades abaixo
|
+-- Modernizando código existente?
| +-- Comece com substituições da Camada 1 (C++20/23)
| +-- Priorize por impacto na segurança (memória > tipos > estilo)
| +-- Consulte anti-patterns.md para a tabela de migração
|
+-- Código crítico para segurança?
| +-- Ative flags de hardening do compilador (veja abaixo)
| +-- Ative o modo hardened do libc++
| +-- Execute sanitizers na CI
| +-- Consulte safe-idioms.md e compiler-hardening.md
|
+-- Usando funcionalidades C++26?
+-- Reflexão: SIM, planeje para ela (GCC 16+)
+-- Contratos: com cautela, para novos limites de API
+-- std::execution: aguarde maturidade do ecossistema
+-- Consulte cpp26-features.md
Camadas de Funcionalidades
Funcionalidades são classificadas por usabilidade prática hoje, não por versão do padrão.
Camada 1: Use Hoje (C++20/23, suporte sólido de compiladores)
| Funcionalidade | Substitui | Padrão |
|---|---|---|
Conceitos + requires | SFINAE, enable_if | C++20 |
| Ranges + views | Laços de iteradores brutos | C++20 |
std::span<T> | Ponteiro + tamanho | C++20 |
std::format | sprintf, cadeias de iostream | C++20 |
Comparação de três vias <=> | Operadores de comparação manuais | C++20 |
std::jthread | std::thread + join manual | C++20 |
| Inicializadores designados | Inicialização posicional de struct | C++20 |
std::expected<T,E> | Códigos de erro, exceções em fronteiras | C++23 |
std::print / std::println | printf, std::cout << | C++23 |
Deducing this | CRTP, duplicação const/não-const | C++23 |
std::flat_map | std::map para uso intenso de leitura | C++23 |
std::optional mônada | Verificações aninhadas em optionals | C++23 |
Consulte cpp20-features.md e cpp23-features.md.
Camada 2: Implemente Agora (sem necessidade de mudar o padrão)
Estas melhoram a segurança sem alterar sua versão do padrão C++:
- Flags de hardening do compilador —
-D_FORTIFY_SOURCE=3,-fstack-protector-strong,-ftrivial-auto-var-init=zero - libc++ com hardening —
-D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_FASTpara verificação de limites com ~0,3% de sobrecarga - Sanitizers na CI — ASan + UBSan como mínimo; TSan para código concorrente
- Flags de aviso —
-Wall -Wextra -Wpedantic -Werror
Consulte compiler-hardening.md.
Camada 3: Planeje (C++26, vale a pena reestruturar em torno)
Reflexão é a funcionalidade mais transformadora do C++26. Ela elimina:
- Boilerplate de serialização (uma função genérica substitui
to_jsonpor struct) - Geradores de código (codegen de protobuf, Qt MOC)
- Registro baseado em macros e hacks de enum para string
O GCC 16 (abril de 2026) tem reflexão mesclada. Planeje novo código para se beneficiar dela.
Camada 4: Observe (C++26, precisa maturação)
- Contratos (
pre/post/contract_assert) — Melhor queassert(), mas sem suporte a funções virtuais e suporte limitado de compiladores. Adote com cautela para novos limites de API. - std::execution (senders/receivers) — Poderoso framework assíncrono, mas curva de aprendizado íngreme, nenhum scheduler acompanha e documentação pobre. Aguarde maturidade do ecossistema.
Consulte cpp26-features.md.
Referência Rápida de Hardening do Compilador
Flags Essenciais (GCC + Clang)
-Wall -Wextra -Wpedantic -Werror
-D_FORTIFY_SOURCE=3
-fstack-protector-strong
-fstack-clash-protection
-ftrivial-auto-var-init=zero
-fPIE -pie
-Wl,-z,relro,-z,now
Específico do Clang
-Wunsafe-buffer-usage
libc++ com Hardening (apenas Clang/libc++)
-D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_FAST
O Google implantou isso no Chrome e em sua frota de servidores: ~0,3% de sobrecarga, 1000+ bugs encontrados, redução de 30% em segfaults de produção.
Consulte compiler-hardening.md para o guia completo.
Racionalizações a Rejeitar
| Racionalização | Por que está errada |
|---|---|
| "Compila sem avisos" | Avisos dependem de quais flags você ativa. Adicione -Wall -Wextra -Wpedantic. |
| "ASan é muito lento para produção" | Use GWP-ASan para detecção baseada em amostragem em produção (~0% de sobrecarga). |
| "Usamos apenas contêineres seguros" | Invalidação de iteradores e acesso não verificado a optional ainda são exploráveis. |
| "Ponteiros inteligentes são mais lentos" | std::unique_ptr tem sobrecarga zero em comparação com ponteiros brutos. Meça antes de afirmar. |
| "Nosso código não tem bugs de memória" | O Google encontrou 1000+ bugs ao ativar o libc++ com hardening. Todo mundo também encontrou. |
| "Funcionalidades C++26 ainda não estão disponíveis" | Funcionalidades C++20/23 estão. Flags de hardening funcionam em qualquer padrão. Comece por aí. |
| "C++ moderno é mais difícil de ler" | std::expected é mais legível do que verificar códigos de erro em 5 parâmetros de saída. |
Checklist de Melhores Práticas
- Use ponteiros inteligentes para propriedade, ponteiros brutos apenas para observação não proprietária
- Prefira
std::spanem vez de ponteiro + tamanho para parâmetros de função - Use
std::expectedpara funções que podem falhar com erros tipados - Restrinja templates com conceitos, não com SFINAE
- Ative flags de hardening do compilador e libc++ com hardening em todas as builds
- Execute ASan + UBSan na CI; adicione TSan para código concorrente
- Use
constexpr/constevalquando possível (livre de UB por design) - Marque funções com
[[nodiscard]]quando ignorar o valor de retorno for provavelmente um bug - Prefira semântica de valor; use
std::variantem vez deunion,enum classem vez deenum - Inicialize todas as variáveis na declaração
Leia a Seguir
- anti-patterns.md — Tabela completa de migração legado-para-moderno (30+ padrões)
- cpp20-features.md — Conceitos, ranges, span, format, coroutines
- cpp23-features.md — expected, print, deducing this, flat_map
- cpp26-features.md — Reflexão, contratos, melhorias de segurança de memória
- compiler-hardening.md — Flags, sanitizers, libc++ com hardening
- safe-idioms.md — Padrões de segurança por classe de vulnerabilidade