Geschichte der Frage:
Normale (rohe) Pointer sind der traditionelle Mechanismus in C++ zur Arbeit mit dynamischem Speicher. Dies ist ein universeller abstrakter Mechanismus, ist jedoch leider sehr fehleranfällig: Speicherlecks, doppelte Löschungen und Dangling Pointer-Fehler. Aus diesem Grund umfasst die Standardbibliothek seit C++11 auch Smart Pointer — Template-Klassen (std::unique_ptr, std::shared_ptr, std::weak_ptr), die automatisch die Lebensdauer des Objekts verwalten.
Problem:
Bei der Verwendung normaler Pointer liegt die Verantwortung für die Zuordnung und Freigabe von Speicher beim Programmierer. Fehler beim Freigeben des Speichers führen zu Lecks (memory leaks), Datenzerstörung, Programmabstürzen. Besonders schwierige Fälle treten bei der Behandlung von Ausnahmen oder bei der Übergabe von Pointern an andere Funktionen auf.
Lösung:
Smart Pointer kapseln den zugewiesenen Speicher und geben ihn automatisch frei, wenn es keine Besitzer mehr gibt. Sie implementieren RAII. std::unique_ptr gewährleistet exklusives Eigentum, std::shared_ptr — geteiltes Eigentum, std::weak_ptr — nicht kontrollierendes (um "Zirkelspeicher" zu verhindern).
Beispielcode:
#include <memory> void foo() { std::unique_ptr<int> p = std::make_unique<int>(5); // Speicher wird auch bei Ausnahme freigegeben // ... }
Wesentliche Merkmale:
Kann man std::unique_ptr für ein Array verwenden, das mit new[] erstellt wurde?
Nein, für Arrays verwenden Sie std::unique_ptr<T[]>: so wird delete[] anstelle von delete aufgerufen.
std::unique_ptr<int[]> arr(new int[10]);
Können Standard-Smart Pointer alle möglichen Speicherlecks verhindern?
Nein. Zum Beispiel führen zirkuläre Verweise zwischen std::shared_ptr zu Lecks. Zum Durchbrechen solcher Zyklen verwendet man std::weak_ptr.
Können Smart Pointer dasselbe Objekt zweimal "löschen"?
Nein, solange die Eigentumslinie nicht verletzt wird (keine rohen Pointer verwenden!). Wenn Sie manuell einen rohen Pointer kopieren, kann die Zerstörung zweimal erfolgen.
Es werden rohe Pointer verwendet, der Speicher wird manuell freigegeben, der Speicher wird bei einer Ausnahme nicht freigegeben.
Vorteile:
Nachteile:
Verwendung von std::unique_ptr und std::make_unique zur Erstellung von Objekten und zur Übergabe an Funktionen.
Vorteile:
Nachteile: