Introducción: por qué el code review en C++ no es para los débiles de corazón
\n\nC++ 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.
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\nEn 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\n1. Fugas de memoria y gestión de recursos (RAII)
\n\nEste 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.
Ejemplo de código malo (bandera roja):
\n\nvoid 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\nEjemplo de código bueno (RAII):
\n\nvoid 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\nQué verificar en un code review de C++:
\n- \n
- ¿Hay
new/deleteen el código? Si es así, ¿por qué? ¿Por qué nostd::make_unique? \n - ¿Se usan
std::unique_ptrpara la propiedad exclusiva? \n - ¿No se pasa
std::shared_ptrpor valor donde bastaría una referencia (es costoso por el contador atómico)? \n - ¿Hay fugas con excepciones (exception safety)? \n
2. Comportamiento indefinido (Undefined Behavior)
\n\nEn 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::moveno 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
Ejemplo de UB (búsquenlo en el code review):
\n\nint& 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\nConsejo 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.
3. Const-correctness: háganlo todo cons
\n\n...