Menu
Coddy logo textTech

Regola del Tre / Cinque / Zero

Fa parte della sezione Programmazione orientata agli oggetti del percorso C++ di Coddy. Lezione 25 di 104.

Quando la tua classe gestisce risorse come la memoria dinamica, hai imparato che ti servono un distruttore personalizzato, un costruttore di copia e un costruttore di spostamento. Ma c'è un principio guida che ti aiuta a decidere quali funzioni membro speciali implementare: la Regola del tre, del cinque e dello zero.

La Regola del Tre afferma: se definisci uno qualsiasi di questi tre elementi, dovresti definirli tutti e tre:

  • Distruttore
  • Costruttore di copia
  • Operatore di assegnazione per copia

La Regola del cinque estende questo principio per il C++ moderno, aggiungendo le operazioni di spostamento:

  • Distruttore
  • Costruttore di copia
  • Operatore di assegnazione per copia
  • Costruttore di spostamento
  • Operatore di assegnazione per spostamento
class Buffer {
    int* data;
    size_t size;
public:
    Buffer(size_t s) : size(s), data(new int[s]) {}
    
    ~Buffer() { delete[] data; }                          // 1. Distruttore
    Buffer(const Buffer& other);                          // 2. Costruttore di copia
    Buffer& operator=(const Buffer& other);               // 3. Assegnazione per copia
    Buffer(Buffer&& other) noexcept;                      // 4. Costruttore di spostamento
    Buffer& operator=(Buffer&& other) noexcept;           // 5. Assegnazione per spostamento
};

La Regola dello Zero è l'approccio più semplice: se la tua classe non gestisce direttamente risorse, non definire nessuna di queste funzioni. Lascia che sia il compilatore a generarle, oppure usa puntatori intelligenti e contenitori standard che gestiscono le risorse al posto tuo.

class Player {
    std::string name;              // std::string gestisce autonomamente la propria memoria
    std::vector<int> scores;       // std::vector gestisce le proprie risorse
public:
    Player(std::string n) : name(n) {}
    // Non servono funzioni di distruzione, copia o spostamento!
};

Seguire queste regole previene bug come la doppia eliminazione, le perdite di memoria e i puntatori pendenti che si verificano quando alcune operazioni sono definite ma ne mancano altre.

challenge icon

Sfida

Facile

Creiamo una classe TextBuffer che segue la Rule of Five: implementa tutte e cinque le funzioni membro speciali per gestire correttamente i dati dei caratteri allocati dinamicamente. Questo mostrerà come le operazioni di copia e spostamento collaborano per creare una classe robusta che gestisce le risorse.

Creerai due file per organizzare il tuo codice:

  • TextBuffer.h: definisci una classe TextBuffer che memorizza il testo in un array di caratteri allocato dinamicamente. La classe deve avere:
    • Membri privati: un puntatore char* chiamato data per il contenuto testuale e un size_t length per la lunghezza della stringa (senza includere il terminatore null)
    • Un costruttore con parametri che accetta una stringa C (const char*), alloca memoria, copia il contenuto e stampa "TextBuffer created: <text>"
    • Un distruttore che libera la memoria (se non è null) e stampa "TextBuffer destroyed"
    • Un costruttore di copia che esegue una copia profonda e stampa "TextBuffer copied"
    • Un operatore di assegnazione per copia che gestisce l'autoassegnazione, libera i dati esistenti, esegue una copia profonda e stampa "TextBuffer copy-assigned". Restituisci *this
    • Un costruttore di spostamento (contrassegnato noexcept) che trasferisce la proprietà e stampa "TextBuffer moved". Lascia la sorgente in uno stato valido e vuoto
    • Un operatore di assegnazione per spostamento (contrassegnato noexcept) che gestisce l'autoassegnazione, libera i dati esistenti, trasferisce la proprietà e stampa "TextBuffer move-assigned". Restituisci *this
    • Un metodo getText() che restituisce il testo memorizzato (restituisci una stringa vuota "" se data è null)
    • Un metodo getLength() che restituisce la lunghezza
  • main.cpp: mostra in azione tutte e cinque le funzioni membro speciali. Leggi una stringa di testo dall'input, poi:
    • Crea un TextBuffer chiamato original con il testo inserito
    • Crea copied usando il costruttore di copia di original
    • Crea another con il testo "Temporary"
    • Usa l'assegnazione per copia: another = original
    • Crea moved costruendolo per spostamento da original usando std::move()
    • Crea target con il testo "Target"
    • Usa l'assegnazione per spostamento: target = std::move(copied)
    • Stampa "--- Final State ---"
    • Stampa "original: <text> (length: <len>)" per ogni buffer: original, copied, moved, another, target

Dopo gli spostamenti, gli oggetti sorgente (original e copied) dovrebbero mostrare un testo vuoto con lunghezza 0, mentre gli oggetti di destinazione contengono i dati trasferiti. Questo mostra in azione la Rule of Five: tutte e cinque le funzioni lavorano insieme per garantire una gestione sicura delle risorse.

Includi <cstring> per funzioni per le stringhe come strlen e strcpy, e <utility> per std::move().

Provalo tu

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

using namespace std;

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

    // TODO: Crea un TextBuffer chiamato 'original' con il testo di input

    // TODO: Crea 'copied' usando il costruttore di copia di 'original'

    // TODO: Crea 'another' con il testo "Temporary"

    // TODO: Usa l'assegnazione per copia: another = original

    // TODO: Crea 'moved' usando il costruttore di spostamento su 'original' con std::move()

    // TODO: Crea 'target' con il testo "Target"

    // TODO: Usa l'assegnazione per spostamento: target = std::move(copied)

    // TODO: Stampa "--- Final State ---"

    // TODO: Stampa lo stato di ogni buffer in questo formato:
    // "original: <text> (length: <len>)"
    // Stampa per: original, copied, moved, another, target

    return 0;
}
quiz iconMettiti alla prova

Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.

Tutte le lezioni di Programmazione orientata agli oggetti

Esercitati da solo: Compilatore C++ online