Code review en C++: qué verificar para que el código no «explote»

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Introducción: por qué el code review en C++ no es para los débiles de corazón

\n\n

C++ es un lenguaje que le otorga al programador un poder increíble. Pero, como decía el tío Ben de «Spider-Man»: «Un gran poder conlleva una gran responsabilidad». Y si en Python puedes mezclar accidentalmente int y str y solo obtener una excepción, en C++ el mismo descuido puede provocar un comportamiento indefinido (UB) que se manifestará un mes después en el servidor del cliente a las 3 de la madrugada.

\n\n

El code review en C++ no es una casilla que marcar en Jira. Es su escudo contra segmentation fault, fugas de memoria y código lento como una tortuga. Muchos desarrolladores (especialmente los que vienen de Java o Python) piensan que el code review es revisar el estilo y los nombres de las variables. En C++ es más profundo. Aquí hay que mirar en el alma misma del programa: la gestión de memoria, RAII, const-correctness y si ese puntero inteligente no les va a disparar en el pie.

\n\n

En este artículo he recopilado una lista de verificación real para revisar código C++. Tómenla como referencia cuando hagan su próximo code review. ¡Allá vamos!

\n\n

1. Fugas de memoria y gestión de recursos (RAII)

\n\n

Este es el sanctasanctórum de C++. Si ven un new sin delete — es una bandera roja. Pero en el C++ moderno (C++11 y posteriores) no deberíamos escribir new manualmente en absoluto. Usen punteros inteligentes: std::unique_ptr, std::shared_ptr. Si el desarrollador usa punteros crudos (int*) para poseer un recurso — es motivo para hacer una pregunta.

\n\n

Ejemplo de código malo (bandera roja):

\n\n
void process() {\n    int* data = new int[1000];\n    // ... algún código ...\n    if (error) {\n        return; // ¡FUGA! delete no se llamó\n    }\n    delete[] data;\n}\n
\n\n

Ejemplo de código bueno (RAII):

\n\n
void process() {\n    std::vector<int> data(1000);\n    // ... código ...\n    if (error) {\n        return; // Todo bien, el vector limpiará la memoria solo\n    }\n}\n
\n\n

Qué verificar en un code review de C++:

\n
    \n
  • ¿Hay new/delete en el código? Si es así, ¿por qué? ¿Por qué no std::make_unique?
  • \n
  • ¿Se usan std::unique_ptr para la propiedad exclusiva?
  • \n
  • ¿No se pasa std::shared_ptr por valor donde bastaría una referencia (es costoso por el contador atómico)?
  • \n
  • ¿Hay fugas con excepciones (exception safety)?
  • \n
\n\n

2. Comportamiento indefinido (Undefined Behavior)

\n\n

En C++, el compilador confía en el programador. Si escriben una tontería, el compilador no los regañará — simplemente generará código que puede hacer cualquier cosa. UB es el azote de C++. Esto es lo que hay que detectar en la revisión:

\n\n
    \n
  • Acceso fuera de los límites del array: arr[10] para un array de 10 elementos.
  • \n
  • Uso de una variable después de moverla: std::move no es magia, el objeto después de moverse está en un estado válido pero indefinido.
  • \n
  • Desbordamiento de enteros con signo: INT_MAX + 1 ¡es UB! (A diferencia de Java, donde solo es un wrap-around).
  • \n
  • Referencia colgante (dangling reference): devolver una referencia a una variable local.
  • \n
\n\n

Ejemplo de UB (búsquenlo en el code review):

\n\n
int& getValue() {\n    int x = 42;\n    return x; // ¡UB! x se destruye al salir de la función\n}\n\nvoid example() {\n    int& ref = getValue();\n    std::cout << ref; // Puede imprimir 42, o basura, o crashear\n}\n
\n\n

Consejo para el revisor: si ven aritmética con int, especialmente en bucles o al trabajar con tamaños — verifiquen si habrá desbordamiento. Es mejor usar size_t para índices y std::ssize() para comparaciones seguras.

\n\n

3. Const-correctness: háganlo todo cons

\n\n

...

Blogs

Book Recommendations