Introdução: por que C++ é difícil, mas interessante
C++ é uma das linguagens de programação mais poderosas e eficientes. Mas com grande poder vem grande responsabilidade. Desenvolvedores iniciantes frequentemente encontram erros que podem levar à queda do programa, vazamentos de memória e comportamento indefinido. Neste artigo, vamos analisar os 10 erros mais comuns de iniciantes em C++ — de A a Z. Você aprenderá como reconhecê-los, corrigi-los e, principalmente, como evitá-los no futuro. O material será útil tanto para estudantes quanto para aqueles que estão começando sua jornada na programação de sistemas.
1. Ignorar o comportamento indefinido (UB)
Um dos erros mais traiçoeiros é o comportamento indefinido (Undefined Behavior, UB). O compilador não emitirá um aviso, o programa pode funcionar "aparentemente normal", mas ao mudar as otimizações ou a plataforma, tudo desmorona.
Exemplo: acesso fora dos limites do array
int arr[5] = {1, 2, 3, 4, 5};
arr[5] = 42; // UB: acesso fora dos limites
std::cout << arr[10]; // UB: leitura de lixo
Como evitar: Sempre use std::array ou std::vector com verificação via .at(), bem como contêineres STL. Nunca confie na "sorte" — o UB pode se manifestar no momento mais inoportuno.
2. Vazamentos de memória e ponteiros brutos
Em C++ não há coletor de lixo. Cada new deve ter um delete correspondente. Iniciantes frequentemente esquecem de liberar memória, especialmente ao lidar com exceções.
Exemplo de vazamento
void leak() {
int* p = new int(100);
// esqueceu delete p;
// ao sair da função, a memória está perdida
}
Solução: Use ponteiros inteligentes: std::unique_ptr para posse exclusiva e std::shared_ptr para posse compartilhada. Eles liberarão a memória automaticamente ao sair do escopo.
void no_leak() {
auto p = std::make_unique<int>(100);
// delete é chamado automaticamente
}
3. Uso incorreto de referências e ponteiros
A confusão entre referências (&) e ponteiros (*) é um problema comum.
- Referência é um apelido. Ela não pode ser
nullptre não pode ser reatribuída. - Ponteiro pode ser nulo e pode apontar para objetos diferentes.
Erro típico: retornar referência a um objeto local
int& bad_ref() {
int x = 10;
return x; // x será destruído após a saída
}
// uso: int& r = bad_ref(); // referência pendente
Regra: Nunca retorne referências ou ponteiros para variáveis locais. Apenas para dados cujo tempo de vida é garantido (por exemplo, argumentos passados por referência ou variáveis estáticas).
4. Negligenciar RAII (Resource Acquisition Is Initialization)
RAII é um idioma chave do C++. O recurso (memória, arquivo, mutex) é adquirido no construtor e liberado no destrutor. Iniciantes frequentemente escrevem gerenciamento manual, o que leva a vazamentos ao lidar com exceções.
Exemplo ruim
void handle_file() {
FILE* f = fopen("data.txt", "r");
// ... trabalho com o arquivo ...
if (some_error) {
return; // esqueceu fclose!
}
fclose(f);
}
Bom exemplo com RAII
void handle_file_safe() {
std::ifstream f("data.txt");
if (!f) return;
// ... trabalho ...
// o arquivo será fechado automaticamente ao sair do escopo
}
Conclusão: Sempre envolva recursos em wrappers RAII. Para arquivos — std::fstream, para memória — ponteiros inteligentes, para mutexes — std::lock_guard.
5. Ignorar const e constexpr
Muitos iniciantes não usam