Costruttori e distruttori rappresentano l'inizio e la
fine del ciclo di vita di un oggetto. Il costruttore
prepara l'oggetto all'uso, inizializzando i dati e
acquisendo eventuali risorse necessarie; il distruttore, invece, si occupa della loro corretta
liberazione.
Costruttori e distruttori nelle
classi: come funzionano davvero.
Pubblicato il: 22-7-2026
Ultima Modifica: 22-7-2026
📖 Introduzione
Quando si inizia a programmare con le classi,
una delle prime domande che ci si pone è:
"Quando viene creato un oggetto?"
e subito dopo:
"Quando viene eliminato?"
La risposta è racchiusa in due strumenti fondamentali
della programmazione orientata agli oggetti:
🟢 Costruttore (Constructor)
🔴 Distruttore (Destructor)
Sono due metodi speciali che il compilatore richiama
automaticamente nei momenti più importanti della vita di un
oggetto.
Comprendere bene il loro funzionamento significa evitare
errori, perdite di memoria e programmi instabili.
In questo articolo vedremo come funzionano davvero, con
numerosi esempi pratici.
🏠 Immaginiamo una casa...
Pensiamo ad una classe come al progetto di una casa.
Ogni volta che costruiamo una nuova casa:
vengono installate porte;
finestre;
impianti;
mobili.
Questa fase corrisponde al costruttore.
Quando invece la casa viene demolita bisogna:
togliere i mobili;
chiudere le utenze;
eliminare i materiali.
Questa è la funzione del distruttore.
Lo stesso accade agli oggetti creati da un programma.
🟢 Cos'è un costruttore?
Il costruttore è una funzione speciale che viene eseguita
automaticamente quando viene creato un oggetto.
Il suo scopo principale è:
✅ inizializzare le variabili
✅ preparare l'oggetto all'uso
✅ allocare eventuale memoria
✅ aprire file
✅ creare connessioni
📌 Caratteristiche del costruttore
Un costruttore:
ha lo stesso nome della classe
non restituisce alcun valore
non possiede tipo di ritorno
viene richiamato automaticamente.
Sintassi:
class Persona { public:
Persona() { // Costruttore }
};
Notare che non compare:
void
oppure
int
perché il costruttore non restituisce nulla.
👤 Primo esempio
#include <iostream>
using namespace std;
class Persona { public:
Persona() { cout << "Oggetto creato." << endl; }
};
int main() { Persona p;
return 0; }
Output
Oggetto creato.
Appena viene creato l'oggetto:
Persona p;
il costruttore viene eseguito automaticamente.
Non serve chiamarlo.
⚙️ Inizializzare le variabili
Uno degli usi più comuni consiste nell'assegnare valori
iniziali.
#include <iostream>
using namespace std;
class Auto { public:
string modello; int anno;
Auto() { modello = "Sconosciuto"; anno = 2025; } };
Prima vengono costruite le classi base, poi quelle
derivate. Durante la distruzione avviene l'opposto.
⚠️ Distruttori virtuali
Quando una classe è pensata per essere usata come
classe base e gli oggetti possono essere eliminati
tramite un puntatore alla classe base, il distruttore
dovrebbe essere dichiarato virtual.
class Cane : public Animale { public: ~Cane() { cout << "Distruttore Cane" << endl; } };
int main() { Animale* a = new Cane();
delete a; }
Output:
Distruttore Cane
Distruttore Animale
Senza il distruttore virtuale, il distruttore della
classe derivata potrebbe non essere eseguito, causando
perdite di risorse.
⚠️ Errori comuni
❌ Dimenticare di liberare la memoria
puntatore = new int[100];
ma mai
delete[] puntatore;
❌ Inserire logica complessa nel distruttore
Il distruttore dovrebbe limitarsi alla pulizia delle
risorse. Operazioni lunghe o che possono generare eccezioni
sono generalmente da evitare.
❌ Inizializzare i membri nel corpo del costruttore
quando è preferibile la lista di inizializzazione
Meglio:
Persona(string n) : nome(n)
{
}
che:
Persona(string n)
{
nome = n;
}
💡 Buone pratiche
✔️ Inizializzare sempre gli oggetti.
✔️ Usare la lista di inizializzazione quando possibile.
✔️ Liberare tutte le risorse acquisite.
✔️ Dichiarare un distruttore virtual
nelle classi base polimorfiche.
✔️ Preferire, quando possibile, contenitori e smart
pointer della libreria standard (std::vector,
std::unique_ptr,
std::shared_ptr) per ridurre la gestione manuale
della memoria.
📚 In sintesi
Costruttori e distruttori rappresentano l'inizio e la
fine del ciclo di vita di un oggetto. Il costruttore
prepara l'oggetto all'uso, inizializzando i dati e
acquisendo eventuali risorse necessarie; il
distruttore, invece, si occupa della loro corretta
liberazione.
Capire quando vengono eseguiti, come utilizzare i
costruttori parametrizzati, il costruttore di copia, la
lista di inizializzazione e l'importanza dei distruttori
virtuali permette di scrivere codice più sicuro, efficiente
e facile da mantenere.
Una buona gestione del ciclo di vita degli oggetti è uno
dei pilastri della programmazione orientata agli oggetti e
costituisce la base per affrontare argomenti più avanzati,
come il principio RAII (Resource Acquisition Is
Initialization), gli smart pointer
e la progettazione di librerie robuste e professionali.