Menu
Coddy logo textTech

Drei-/Fünf-/Null-Regel

Teil des Abschnitts Objektorientierte Programmierung der C++-Journey von Coddy. Lektion 25 von 104.

Wenn deine Klasse Ressourcen wie dynamischen Speicher verwaltet, hast du gelernt, dass du einen benutzerdefinierten Destruktor, Kopierkonstruktor und Verschiebekonstruktor benötigst. Es gibt jedoch ein Leitprinzip, das dir bei der Entscheidung hilft, welche speziellen Memberfunktionen du implementieren solltest: die Rule of Three, Five, and Zero.

Die Rule of Three besagt: Wenn du eines dieser drei Elemente definierst, solltest du alle drei definieren:

  • Destruktor
  • Kopierkonstruktor
  • Kopierzuweisungsoperator

Die Rule of Five erweitert dies für modernes C++ um Verschiebeoperationen:

  • Destruktor
  • Kopierkonstruktor
  • Kopierzuweisungsoperator
  • Verschiebekonstruktor
  • Verschiebezuweisungsoperator
class Buffer {
    int* data;
    size_t size;
public:
    Buffer(size_t s) : size(s), data(new int[s]) {}
    
    ~Buffer() { delete[] data; }                          // 1. Destruktor
    Buffer(const Buffer& other);                          // 2. Kopierkonstruktor
    Buffer& operator=(const Buffer& other);               // 3. Kopierzuweisung
    Buffer(Buffer&& other) noexcept;                      // 4. Move-Konstruktor
    Buffer& operator=(Buffer&& other) noexcept;           // 5. Move-Zuweisung
};

Die Rule of Zero ist der einfachste Ansatz: Wenn deine Klasse Ressourcen nicht direkt verwaltet, definiere keine dieser Funktionen. Lass den Compiler sie generieren oder verwende Smart Pointer und Standardcontainer, die Ressourcen für dich verwalten.

class Player {
    std::string name;              // std::string verwaltet seinen eigenen Speicher
    std::vector<int> scores;       // std::vector verwaltet seine Ressourcen
public:
    Player(std::string n) : name(n) {}
    // Kein Destruktor, keine Copy- oder Move-Funktionen nötig!
};

Das Befolgen dieser Regeln verhindert Fehler wie doppeltes Löschen, Speicherlecks und hängende Zeiger, die auftreten, wenn einige Operationen definiert sind, andere jedoch fehlen.

challenge icon

Aufgabe

Einfach

Lass uns eine TextBuffer-Klasse erstellen, die der „Rule of Five“ folgt: Sie implementiert alle fünf speziellen Memberfunktionen, um dynamisch zugewiesene Zeichendaten ordnungsgemäß zu verwalten. Dies zeigt, wie Kopier- und Verschiebeoperationen zusammenwirken, um eine robuste, Ressourcen verwaltende Klasse zu erstellen.

Du erstellst zwei Dateien, um deinen Code zu organisieren:

  • TextBuffer.h: Definiere eine TextBuffer-Klasse, die Text in einem dynamisch zugewiesenen Zeichenarray speichert. Deine Klasse benötigt:
    • Private Member: einen char*-Zeiger namens data für den Textinhalt und eine size_t length für die Stringlänge (ohne den Nullterminator)
    • Einen parametrisierten Konstruktor, der einen C-String (const char*) entgegennimmt, Speicher reserviert, den Inhalt kopiert und "TextBuffer created: <text>" ausgibt
    • Einen Destruktor, der den Speicher freigibt (falls er nicht null ist) und "TextBuffer destroyed" ausgibt
    • Einen Kopierkonstruktor, der eine tiefe Kopie durchführt und "TextBuffer copied" ausgibt
    • Einen Kopierzuweisungsoperator, der Selbstzuweisung behandelt, vorhandene Daten bereinigt, eine tiefe Kopie durchführt und "TextBuffer copy-assigned" ausgibt. Gib *this zurück
    • Einen Verschiebekonstruktor (mit noexcept gekennzeichnet), der den Besitz überträgt und "TextBuffer moved" ausgibt. Hinterlasse die Quelle in einem gültigen leeren Zustand
    • Einen Verschiebezuweisungsoperator (mit noexcept gekennzeichnet), der Selbstzuweisung behandelt, vorhandene Daten bereinigt, den Besitz überträgt und "TextBuffer move-assigned" ausgibt. Gib *this zurück
    • Eine getText()-Methode, die den gespeicherten Text zurückgibt (gib eine leere Zeichenkette "" zurück, wenn data null ist)
    • Eine getLength()-Methode, die die Länge zurückgibt
  • main.cpp: Zeige alle fünf speziellen Memberfunktionen in Aktion. Lies eine Textzeichenkette von der Eingabe ein und:
    • Erstelle einen TextBuffer namens original mit dem eingegebenen Text
    • Erstelle copied mithilfe des Kopierkonstruktors aus original
    • Erstelle another mit dem Text "Temporary"
    • Verwende die Kopierzuweisung: another = original
    • Erstelle moved, indem du aus original mithilfe von std::move() einen Verschiebekonstruktor verwendest
    • Erstelle target mit dem Text "Target"
    • Verwende die Verschiebezuweisung: target = std::move(copied)
    • Gib "--- Final State ---" aus
    • Gib für jeden Puffer — original, copied, moved, another, target — "original: <text> (length: <len>)" aus

Nach den Verschiebeoperationen sollten die Quellobjekte (original und copied) einen leeren Text mit der Länge 0 anzeigen, während die Zielobjekte die übertragenen Daten enthalten. Dies demonstriert die „Rule of Five“ in Aktion: Alle fünf Funktionen arbeiten zusammen, um eine sichere Ressourcenverwaltung zu gewährleisten.

Binde <cstring> für Stringfunktionen wie strlen und strcpy sowie <utility> für std::move() ein.

Probier es selbst

#include <iostream>
#include <string>
#include <utility>
#include "TextBuffer.h"

using namespace std;

int main() {
    string input;
    getline(cin, input);

    // TODO: Erstelle einen TextBuffer namens 'original' mit dem Eingabetext

    // TODO: Erstelle 'copied' mithilfe des Copy-Konstruktors von 'original'

    // TODO: Erstelle 'another' mit dem Text "Temporary"

    // TODO: Verwende Copy-Zuweisung: another = original

    // TODO: Erstelle 'moved' durch Move-Konstruktion von 'original' mit std::move()

    // TODO: Erstelle 'target' mit dem Text "Target"

    // TODO: Verwende Move-Zuweisung: target = std::move(copied)

    // TODO: Gib "--- Final State ---" aus

    // TODO: Gib den Zustand jedes Buffers in diesem Format aus:
    // "original: <text> (length: <len>)"
    // Gib aus für: original, copied, moved, another, target

    return 0;
}
quiz iconTeste dich selbst

Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.

Alle Lektionen in Objektorientierte Programmierung

Übe selbstständig: Online-C++-Compiler