Code-Review in C++: Was man prüfen und wie man Feedback in der Praxis geben sollte
\n\nCode-Review ist nicht nur eine Formalität, sondern ein mächtiges Werkzeug zur Verbesserung der Codequalität. In C++ ist das Review aufgrund der Komplexität der Sprache besonders wichtig: Manuelle Speicherverwaltung, Templates, Mehrfachvererbung. In diesem Artikel werden wir untersuchen, worauf man bei der Überprüfung von C++-Code achten und wie man Anmerkungen so formulieren sollte, dass sie hilfreich und nicht verletzend sind.
\n\n1. Speichersicherheit und RAII
\n\nDas Erste, was überprüft werden sollte, ist das Ressourcenmanagement. In C++ gibt es keinen Garbage Collector, daher sind Speicherlecks und doppelte Freigaben ein häufiges Problem. Das Schlüsselmuster ist RAII (Resource Acquisition Is Initialization).
\n\nWas prüfen:
\n- \n
- Werden Smart Pointer (
std::unique_ptr,std::shared_ptr) anstelle von rohennew/deleteverwendet? \n - Gibt es manuelle
delete-Aufrufe im Code? (Außer in seltenen Fällen von Low-Level-Arbeit) \n - Sind RAII-Klassen korrekt implementiert: Wird die Ressource im Konstruktor erfasst und im Destruktor freigegeben? \n
- Wurde der virtuelle Destruktor in der Basisklasse nicht vergessen? \n
// ❌ Schlecht: Manuelle Verwaltung\nvoid process() {\n int* data = new int[100];\n // ... wenn eine Ausnahme auftritt, Speicherleck\n delete[] data;\n}\n\n// ✅ Gut: RAII mit std::vector\nvoid process() {\n std::vector<int> data(100);\n // sicher bei Ausnahmen\n}\n\nWie man Feedback gibt: Sagen Sie statt „Du hast vergessen, den Speicher freizugeben“: „Hier wäre es besser, std::vector oder std::unique_ptr zu verwenden – das gibt Ressourcen automatisch frei und macht den Code ausnahmesicher.“
2. Const-Correctness und Referenzen
\n\nC++ erlaubt es, explizit anzugeben, dass Daten nicht geändert werden sollen. Das verbessert die Lesbarkeit und ermöglicht dem Compiler eine bessere Optimierung des Codes.
\n\nWas prüfen:
\n- \n
- Sind alle Parameter, die nicht geändert werden, mit
constmarkiert? \n - Werden große Objekte per Konstante-Referenz (
const T&) übergeben, anstatt per Wert? \n - Sind Methoden, die das Objekt nicht ändern, als
constmarkiert? \n - Wird
const_castohne zwingende Notwendigkeit verwendet? \n
// ❌ Schlecht: Kopieren eines großen Objekts\nstd::string toUpper(std::string s); // Kopie\n\n// ✅ Gut: Konstante-Referenz\nstd::string toUpper(const std::string& s); // ohne Kopie\n\n// ❌ Schlecht: Methode nicht const, obwohl sie den Zustand nicht ändert\nclass Point {\n int x, y;\npublic:\n int getX() { return x; } // sollte const sein\n};\n\n// ✅ Gut\nint getX() const { return x; }\n\nWie man Feedback gibt: „Fügen wir const für Parameter hinzu, die nicht geändert werden – das macht die Schnittstelle klarer und verhindert versehentliche Änderungen.“
\n\n3. Verwendung von STL und Algorithmen
\n\nDie Standardbibliothek von C++ enthält viele vorgefertigte Lösungen. Das Neuerfinden des Rades ist ein häufiger Fehler von Anfängern.
\n\nWas prüfen:
\n- \n
- Gibt es manuelle Schleifen, die durch Algorithmen ersetzt werden können (
std::find,std::sort,std::transform)? \n - Ist der Container richtig gewählt? (
std::vectorfür wahlfreien Zugriff,std::listfür häufige Einfügungen in der Mitte) \n - Werden
std::string_viewzur Übergabe von Strings ohne Kopie verwendet? \n - Wurde
reserve()fürstd::vectorbei bekannter Größe nicht vergessen? \n
// ❌ Schlecht: Manuelle Suche\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// ✅ Gut: Verwendung von STL\nbool contains(c