Einleitung
C++ ist eine leistungsstarke und flexible Programmiersprache, die dem Entwickler enorme Kontrolle über die Systemressourcen gibt. Diese Freiheit bringt jedoch eine hohe Verantwortung mit sich. Anfänger machen oft dieselben Fehler, die zu schwer auffindbaren Bugs, Speicherlecks und undefiniertem Verhalten führen können. In diesem Artikel analysieren wir die Top-Fehler von C++-Anfängern und zeigen, wie man sie vermeidet.
1. Speicherlecks und falsches Ressourcenmanagement
Problem: Manuelle Speicherverwaltung mit new/delete
Einer der häufigsten Fehler ist es, delete für ein mit new erstelltes Objekt zu vergessen. Dies führt zu einem Speicherleck.
void example() { int* ptr = new int(42); // ... irgendein Code ... // delete ptr; vergessen}In komplexeren Fällen, wenn zwischen new und delete eine Exception auftritt, wird der Speicher ebenfalls nicht freigegeben.
Lösung: Verwenden Sie RAII und Smart Pointer
C++11 und neuere Standards bieten Smart Pointer, die die Lebensdauer eines Objekts automatisch verwalten.
#include <memory>
void example() { std::unique_ptr<int> ptr = std::make_unique<int>(42); // Der Speicher wird automatisch freigegeben, wenn der Gültigkeitsbereich verlassen wird}Verwenden Sie für Arrays std::vector anstelle der manuellen Verwaltung:
// Schlecht:int* arr = new int[100];// ... Arbeit ...delete[] arr;
// Gut:std::vector<int> arr(100);// Der Speicher wird automatisch verwaltet2. Undefiniertes Verhalten (Undefined Behavior)
Problem: Array-Index außerhalb des gültigen Bereichs
In C++ gibt es keine eingebaute Grenzprüfung für rohe Arrays. Der Zugriff auf ein Element außerhalb des Arrays ist klassisches undefiniertes Verhalten.
int arr[5] = {1, 2, 3, 4, 5};arr[10] = 42; // Undefiniertes Verhalten! Kann "funktionieren" oder abstürzenLösung: Verwenden Sie std::array und std::vector mit at()
#include <vector>#include <array>
std::array<int, 5> arr = {1, 2, 3, 4, 5};// arr.at(10) wirft eine std::out_of_range-Exception
std::vector<int> vec = {1, 2, 3};vec.at(5); // Sichere GrenzprüfungProblem: Verwendung nicht initialisierter Variablen
int x;std::cout << x; // Undefiniertes Verhalten: x ist nicht initialisiertInitialisieren Sie Variablen immer:
int x = 0;int* ptr = nullptr;3. Verwechslung von Pointern und Referenzen
Problem: Rückgabe eines Pointers auf ein lokales Objekt
int* getBadPointer() { int local = 42; return &local; // Fehler! local wird beim Verlassen der Funktion zerstört}Dies führt zu einem hängenden Zeiger (dangling pointer). Die Verwendung eines solchen Pointers ist undefiniertes Verhalten.
Lösung: Geben Sie by Value zurück oder verwenden Sie Smart Pointer
// Rückgabe by Value (bevorzugt für einfache Typen)int getValue() { return 42;}
// Rückgabe eines Smart Pointers für dynamische Objektestd::unique_ptr<MyClass> createObject() { return std::make_unique<MyClass>();}Problem: Verwechslung von Referenzen und Pointern
Referenzen können nicht nullptr sein und können nicht neu zugewiesen werden. Pointer können das. Anfänger versuchen oft, nullptr an eine Funktion zu übergeben, die eine Referenz erwartet.
void process(int& ref) { // ref referenziert garantiert ein existierendes Objekt}
int* ptr = nullptr;// process(*ptr); // Fehler! Dereferenzierung von nullptr — UBVerwenden Sie Referenzen, wenn das Objekt zwingend erforderlich ist, und Pointer (oder std::optional), wenn null möglich sein soll.