🛡️ Modern C++20 Memory Safety

C++ 10: Smart Pointer & Speichersicherheit

Schluss mit Memory Leaks und Dangling Pointern: Beherrsche std::unique_ptr, std::shared_ptr, std::weak_ptr und RAII Custom Deleter in Modern C++20.

🔐 1. Exklusiver Besitz: std::unique_ptr & std::make_unique

Ein std::unique_ptr besitzt eine Heap-Ressource exklusiv. Er kann nicht kopiert, sondern nur via Move-Semantik (std::move) übertragen werden. Sobald der Smart Pointer den Gültigkeitsbereich (Scope) verlässt, wird der Speicher automatisch freigegeben:

#include <memory>
#include <iostream>

struct Connection {
    int id;
    Connection(int i) : id(i) { std::cout << "Connect " << id << "\n"; }
    ~Connection() { std::cout << "Disconnect " << id << "\n"; }
};

void process_connection(std::unique_ptr<Connection> conn) {
    std::cout << "Processing connection " << conn->id << "\n";
} // conn wird HIER automatisch zerstört!

int main() {
    // Bevorzugt: std::make_unique (Ausnahmesicher & effizient)
    auto c1 = std::make_unique<Connection>(101);

    // FEHLER (Kopieren verboten): auto c2 = c1;
    // KORREKT (Besitz übertragen):
    process_connection(std::move(c1));
    // c1 ist jetzt nullptr
}
🏢 Didaktische Analogie: Der Generalschlüssel

Ein std::unique_ptr ist wie ein physischer Original-Schlüssel zu einem Hotelsafe. Es gibt keine Duplikate. Wenn du den Schlüssel an einen Kollegen übergibst (std::move), sind deine eigenen Hände leer (nullptr). Beim Auschecken schließt der Schlüssel den Safe automatisch ab und löscht den Inhalt!

🤝 2. Geteilter Besitz: std::shared_ptr & std::weak_ptr

Ein std::shared_ptr verwaltet Ressourcen über einen Referenzzähler (Reference Count). Erst wenn die letzte Kopie zerstört wird (Count == 0), wird das Objekt freigegeben. Um zyklische Referenzen (Memory Leaks) zu verhindern, verwenden wir std::weak_ptr:

#include <memory>

struct Node {
    int value;
    std::shared_ptr<Node> next;
    std::weak_ptr<Node> prev; // Verhindert zirkuläre Referenz!

    Node(int v) : value(v) {}
};

int main() {
    auto n1 = std::make_shared<Node>(1);
    auto n2 = std::make_shared<Node>(2);

    n1->next = n2;
    n2->prev = n1; // Schwache Referenz erhöht den Shared Count nicht

    if (auto parent = n2->prev.lock()) {
        std::cout << "Parent existiert noch: " << parent->value << "\n";
    }
}

⚙️ 3. RAII Custom Deleters für C-Ressourcen

Smart Pointer können auch nicht-speicherbasierte OS-Handles (wie Dateideskriptoren, Sockets oder Mutexes) automatisch schließen:

#include <cstdio>
#include <memory>

// Custom Deleter für C-Dateizeiger
auto file_deleter = [](FILE* fp) {
    if (fp) {
        std::fclose(fp);
        std::cout << "File handle safely closed.\n";
    }
};

using SafeFile = std::unique_ptr<FILE, decltype(file_deleter)>;

SafeFile open_safe_file(const char* filename, const char* mode) {
    FILE* fp = std::fopen(filename, mode);
    return SafeFile(fp, file_deleter);
}

📑 4. Cheat-Sheet: Smart Pointer Vergleich

Smart Pointer Typ Besitzmodell Kopierbar / Bewegbar Typischer Anwendungsfall
std::unique_ptr<T> Exklusiv (1 Besitzer) Nur Move (std::move) Standard-Allokation, Factory Methods, RAII Guards
std::shared_ptr<T> Geteilt (Ref Count) Copy & Move erlaubt Gemeinsame Ressourcen, Graph-Kanten, Caches
std::weak_ptr<T> Nicht-besitzend (Observer) Copy & Move Backpointer (Parent), Caching, Cycle-Breaking
T* (Raw Pointer) Kein Besitz (Observer) Copy & Move Nur noch für optionale Parameter / Beobachtung

🧠 Diagnostischer Selbst-Check

Überprüfe dein Verständnis zu Speichersicherheit, Syntax und Systems-Design mit gezieltem Feedback:

🎯 Aufgaben & Checkliste in aufgabe.cpp

💡 Modern C++ Regel: Kein manuelles new / delete mehr!

Im modernen C++ (seit C++14/C++20) gibt es fast keinen legitimen Grund mehr, new oder delete direkt im Anwendungscode aufzurufen. Verwende stattdessen konsequent std::make_unique und std::make_shared!

💻 In Web-IDE öffnen → Weiter zu C++ 11 →