Revisão de código em C++: o que verificar e como dar feedback
\n\nCode review é uma das etapas-chave do desenvolvimento de software. Isso é especialmente importante para C++, onde erros de gerenciamento de memória ou uso incorreto da biblioteca padrão podem levar a problemas sérios. Neste artigo, vamos analisar o que observar ao revisar código em C++ e como dar feedback para que ele seja útil, e não ofensivo.
\n\nPor que o code review é importante para C++?
\n\nC++ é uma linguagem poderosa, mas complexa. Ela oferece ao desenvolvedor um alto nível de controle, mas exige atenção. Problemas típicos: vazamentos de memória, comportamento indefinido, algoritmos ineficientes. Um bom code review ajuda a identificar esses erros antes que eles cheguem à produção.
\n\nPara desenvolvedores iniciantes, o code review não é apenas uma verificação, mas também um aprendizado. Ao receber feedback, você aprende a escrever código de melhor qualidade. Ao fazer a revisão, aprende a analisar e argumentar.
\n\nO que verificar no código C++: checklist
\n\nPara que a revisão seja sistemática, use o seguinte checklist.
\n\n1. Gerenciamento de memória e recursos
\n\nEste é o fundamento do C++. Erros aqui são os mais perigosos.
\n- \n
- Ponteiros inteligentes estão sendo usados em vez de ponteiros brutos?
std::unique_ptrestd::shared_ptrdevem ser o padrão. Ponteiros brutos são permitidos apenas para observação (non-owning). \n - Há vazamentos? Verifique se cada
newtem umdeletecorrespondente (se não estiver usando ponteiros inteligentes). \n - Os recursos estão sendo liberados corretamente? Arquivos, sockets, mutexes devem ser encapsulados em classes RAII. \n
// Ruim: ponteiro bruto e gerenciamento manual\nvoid process() {\n int* data = new int[100];\n // ... se houver uma exceção aqui, haverá vazamento\n delete[] data;\n}\n\n// Bom: ponteiro inteligente\nvoid process() {\n auto data = std::make_unique<int[]>(100);\n // a memória será liberada automaticamente\n}\n\n2. Segurança de tipos e prevenção de comportamento indefinido
\n\nC++ está repleto de comportamento indefinido (UB). O revisor deve estar atento.
\n- \n
- Não há acesso fora dos limites do array? Use
std::arrayoustd::vectorcom.at()em vez de arrays brutos. \n - O casting de tipos está correto? Evite C-style cast. Use
static_cast,dynamic_cast,const_castoureinterpret_castde forma consciente. \n - Todas as variáveis estão inicializadas? Variáveis não inicializadas são uma causa comum de UB. \n
- Não há estouro de inteiros com sinal? Em C++, isso é UB. \n
// Ruim: C-style cast e variável não inicializada\nint* p = (int*)malloc(sizeof(int));\nint x; // não inicializado\n*p = x; // UB\n\n// Bom: casting explícito e inicialização\nint* p = static_cast<int*>(std::malloc(sizeof(int)));\nint x = 0;\n*p = x;\n\n3. Desempenho e eficiência
\n\nNem sempre é necessário buscar velocidade, mas gargalos óbvios devem ser corrigidos.
\n- \n
- Objetos estão sendo passados por valor desnecessariamente? Objetos grandes devem ser passados por referência constante (
const &). \n - Não há cópias desnecessárias? Use move semantics quando apropriado. \n
- O contêiner foi escolhido corretamente?
std::vectorpara acesso rápido por índice,std::listpara inserções frequentes no meio. \n - Uma função virtual não está sendo chamada em um loop intenso? Isso pode ser lento. \n
// Lento: cópia de um objeto grande\nvoid process(std::string s) { /* ... */ }\n\n// Rápido: passagem por referência constante\nvoid process(c