Sobes.tech
Middle

Was wissen Sie über Smart Pointers in C++?

sobes.tech KI

Antwort von AI

Intelligente Zeiger sind RAII-Wrapper um normale (rohe) Zeiger in C++, die eine automatische Verwaltung der Lebensdauer des zugewiesenen Speichers bieten und Lecks verhindern.

Die Haupttypen intelligenter Zeiger in der Standardbibliothek von C++:

  • std::unique_ptr
  • std::shared_ptr
  • std::weak_ptr

std::unique_ptr

  • Besitzt die Ressource exklusiv.
  • Kann nicht kopiert werden, aber verschoben.
  • Wird für die exklusive Besitzübertragung der Ressource verwendet.
  • Die Overhead-Kosten sind minimal, vergleichbar mit einem rohen Zeiger.
// Beispiel für unique_ptr
#include <memory>
#include <iostream>

int main() {
    std::unique_ptr<int> ptr = std::make_unique<int>(10);
    std::cout << *ptr << std::endl; // 10
    // std::unique_ptr<int> ptr2 = ptr; // Kompilierungsfehler: unique_ptr kann nicht kopiert werden
    std::unique_ptr<int> ptr3 = std::move(ptr); // Besitzübertragung
    std::cout << *ptr3 << std::endl; // 10
    // std::cout << *ptr << std::endl; // Undefined behavior: ptr ist jetzt leer
    return 0;
}

std::shared_ptr

  • Ermöglicht mehreren Zeigern, gemeinsam eine Ressource zu besitzen.
  • Verwendet einen Referenzzähler. Der Speicher wird freigegeben, wenn der Zähler auf null sinkt.
  • Kann kopiert werden. Jede Kopie erhöht den Referenzzähler.
  • Hat höhere Overhead-Kosten im Vergleich zu unique_ptr aufgrund der Verwaltung des Zählers.
// Beispiel für shared_ptr
#include <memory>
#include <iostream>

int main() {
    std::shared_ptr<int> ptr1 = std::make_shared<int>(20);
    std::cout << *ptr1 << " (use_count: " << ptr1.use_count() << ")" << std::endl; // 20 (use_count: 1)
    std::shared_ptr<int> ptr2 = ptr1; // Kopie, erhöht use_count
    std::cout << *ptr1 << " (use_count: " << ptr1.use_count() << ")" << std::endl; // 20 (use_count: 2)
    std::shared_ptr<int> ptr3 = ptr1; // Weitere Kopie
    std::cout << *ptr1 << " (use_count: " << ptr1.use_count() << ")" << std::endl; // 20 (use_count: 3)
    return 0;
}

std::weak_ptr

  • Besitzt die Ressource nicht und erhöht den Referenzzähler nicht.
  • Wird verwendet, um zyklische Referenzen zwischen shared_ptr zu vermeiden.
  • Ermöglicht den Zugriff auf die Ressource, auf die shared_ptr zeigt, verhindert aber nicht deren Löschung.
  • Um auf die Ressource zuzugreifen, muss weak_ptr in shared_ptr umgewandelt werden, mittels der Methode lock().
// Beispiel für weak_ptr
#include <memory>
#include <iostream>

int main() {
    std::shared_ptr<int> shared_ptr_int = std::make_shared<int>(30);
    std::weak_ptr<int> weak_ptr_int = shared_ptr_int;

    if (auto locked_ptr = weak_ptr_int.lock()) {
        std::cout << *locked_ptr << std::endl; // 30
    } else {
        std::cout << "Ressource wurde freigegeben." << std::endl;
    }

    shared_ptr_int.reset(); // Ressource wird freigegeben

    if (auto locked_ptr = weak_ptr_int.lock()) {
        std::cout << *locked_ptr << std::endl;
    } else {
        std::cout << "Ressource wurde freigegeben." << std::endl; // Ressource wurde freigegeben.
    }
    return 0;
}

Die Verwendung intelligenter Zeiger ist eine bewährte Praxis in modernem C++, da sie die Wahrscheinlichkeit von Speicherverwaltungsfehlern erheblich reduziert.