Revue de code en C++ : quoi vérifier et comment donner un retour d'expérience en pratique
\n\nLa revue de code n'est pas qu'une simple formalité, mais un outil puissant pour améliorer la qualité du code. En C++, la revue est particulièrement importante en raison de la complexité du langage : gestion manuelle de la mémoire, templates, héritage multiple. Dans cet article, nous allons voir sur quoi se concentrer lors de la vérification du code C++ et comment formuler des remarques pour qu'elles soient utiles, et non blessantes.
\n\n1. Sécurité mémoire et RAII
\n\nLa première chose à vérifier est la gestion des ressources. En C++, il n'y a pas de ramasse-miettes, donc les fuites mémoire et les doubles libérations sont des problèmes courants. Le modèle clé est le RAII (Resource Acquisition Is Initialization).
\n\nQue vérifier :
\n- \n
- Utilise-t-on des pointeurs intelligents (
std::unique_ptr,std::shared_ptr) au lieu denew/deletebruts ? \n - Y a-t-il des appels manuels à
deletedans le code ? (Sauf cas rares de travail bas niveau) \n - Les classes RAII sont-elles correctement implémentées : la ressource est acquise dans le constructeur et libérée dans le destructeur ? \n
- N'a-t-on pas oublié un destructeur virtuel dans la classe de base ? \n
// ❌ Mauvais : gestion manuelle\nvoid process() {\n int* data = new int[100];\n // ... si une exception survient, la mémoire fuit\n delete[] data;\n}\n\n// ✅ Bon : RAII via std::vector\nvoid process() {\n std::vector<int> data(100);\n // sûr en cas d'exception\n}\n\nComment donner un retour d'expérience : Au lieu de « Tu as oublié de supprimer la mémoire », dites : « Il serait préférable d'utiliser std::vector ou std::unique_ptr ici — cela libérera automatiquement les ressources et rendra le code sûr face aux exceptions ».
2. Const-correctness et références
\n\nC++ permet d'indiquer explicitement que les données ne doivent pas être modifiées. Cela améliore la lisibilité et permet au compilateur d'optimiser le code.
\n\nQue vérifier :
\n- \n
- Tous les paramètres qui ne sont pas modifiés sont-ils marqués
const? \n - Les gros objets sont-ils passés par référence constante (
const T&), et non par valeur ? \n - Les méthodes qui ne modifient pas l'objet sont-elles marquées
const? \n const_castn'est-il pas utilisé sans nécessité absolue ? \n
// ❌ Mauvais : copie d'un gros objet\nstd::string toUpper(std::string s); // copie\n\n// ✅ Bon : référence constante\nstd::string toUpper(const std::string& s); // sans copie\n\n// ❌ Mauvais : méthode non const alors qu'elle ne modifie pas l'état\nclass Point {\n int x, y;\npublic:\n int getX() { return x; } // devrait être const\n};\n\n// ✅ Bon\nint getX() const { return x; }\n\nComment donner un retour d'expérience : « Ajoutons const pour les paramètres qui ne sont pas modifiés — cela rendra l'interface plus claire et évitera des modifications accidentelles ».
\n\n3. Utilisation de la STL et des algorithmes
\n\nLa bibliothèque standard C++ contient de nombreuses solutions prêtes à l'emploi. Réinventer la roue est une erreur courante chez les débutants.
\n\nQue vérifier :
\n- \n
- N'y a-t-il pas de boucles manuelles qui pourraient être remplacées par des algorithmes (
std::find,std::sort,std::transform) ? \n - Le conteneur est-il bien choisi ? (
std::vectorpour un accès aléatoire,std::listpour des insertions fréquentes au milieu) \n - Utilise-t-on
std::string_viewpour passer des chaînes sans copie ? \n - N'a-t-on pas oublié
reserve()pourstd::vectorlorsque la taille est connue ? \n
// ❌ Mauvais : recherche manuelle\nbool contains(const std::vector<int>& v, int val) {\n for (size_t i = 0; i < v.size(); ++i) {\n if (v[i] == val) return true;\n }\n return false;\n}\n\n// ✅ Bon : utilisation de la STL\nbool contains(c