Pattern del distruttore
Fa parte della sezione Programmazione orientata agli oggetti del percorso C di Coddy. Lezione 13 di 61.
Ogni oggetto creato con malloc deve essere infine liberato. Proprio come abbiamo scritto una funzione create_ per gestire l'allocazione, scriviamo una funzione free_ per gestire la pulizia. Questo è il modello del distruttore.
L’intuizione chiave è che la liberazione deve avvenire in ordine inverso rispetto all’allocazione. Se il tuo costruttore ha allocato prima i membri interni e poi la struct stessa, il tuo distruttore deve liberare prima i membri della struct e poi la struct:
typedef struct {
char *name;
int age;
} Person;
void free_person(Person *p) {
if (p == NULL) return; // Controllo di sicurezza
free(p->name); // Libera prima il membro interno
free(p); // Poi libera la struct stessa
}
Il controllo NULL all'inizio previene gli arresti anomali se qualcuno passa accidentalmente un puntatore non valido. Dopo aver liberato la stringa interna name, liberiamo la struct stessa. Se liberassimo prima p, perderemmo l'accesso a p->name e causeremmo una perdita di memoria.
Usare il distruttore è semplice:
Person *alice = create_person("Alice", 30);
// ... usa alice ...
free_person(alice); // Libera le risorse quando hai finito
Questo schema assicura che tutta la memoria venga rilasciata correttamente. Senza di esso, ogni oggetto che crei causerebbe una perdita di memoria fino a esaurire la memoria disponibile per il programma.
Sfida
FacileCostruiamo un modulo Movie che dimostra l'intero ciclo di vita di un oggetto: sia la creazione sia la distruzione. Ti eserciterai a scrivere una funzione distruttrice che libera correttamente tutta la memoria allocata nell'ordine giusto.
Creerai tre file:
movie.h: dichiara una structMoviecon due membri:char *title(una stringa allocata dinamicamente) eint year. Dichiara sia un costruttorecreate_movieche accetta un titolo e un anno, sia un distruttorefree_movieche accetta un puntatore a Movie. Usa le protezioni dalle inclusioni multiple con il simboloMOVIE_H.movie.c: implementa entrambe le funzioni. Il costruttore deve allocare memoria per la struct e per la sua stringa del titolo (non dimenticare il terminatore nullo). Il distruttore deve liberare la memoria nell'ordine inverso rispetto all'allocazione: prima la stringa internatitle, poi la struct stessa. Per sicurezza, inserisci un controllo NULL all'inizio del distruttore.main.c: crea un film, visualizza le sue informazioni, quindi libera correttamente la memoria.
Riceverai due input: il titolo del film (una stringa) e l'anno di uscita (un intero).
Nel file principale, usa create_movie per creare un nuovo film, stampane le informazioni, quindi chiama free_movie per liberare tutta la memoria. Dopo averla liberata, stampa un messaggio di conferma.
Stampa l'output in questo formato:
Movie: {title} ({year})
Memory freedPer esempio, con gli input Inception e 2010, l'output sarebbe:
Movie: Inception (2010)
Memory freedRicorda: la chiave per un distruttore corretto è liberare la memoria nell'ordine inverso. Ciò che il costruttore alloca per primo viene liberato per ultimo, mentre ciò che alloca per ultimo viene liberato per primo.
Provalo tu
#include <stdio.h>
#include <stdlib.h>
#include "movie.h"
int main() {
char title[100];
int year;
// Leggi l'input
scanf("%[^\n]", title);
scanf("%d", &year);
// TODO: Crea un film usando create_movie
// TODO: Stampa le informazioni del film nel formato:
// Movie: {title} ({year})
// TODO: Libera la memoria del film usando free_movie
// TODO: Stampa "Memory freed"
return 0;
}
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
1Basi di programmazione modulare
File di intestazioneGuardie di inclusioneFile sorgenteFunzioni staticheRipasso: calcolatrice modulare4Incapsulamento
Il concetto di puntatori opachiDefinire struct opacheGetter e setterLa convalida nei setterRiepilogo: scatola segreta2Oggetti e metodi
Le struct come oggettiIl puntatore 'Self'Correttezza constPuntatore o valoreMetodi di supportoRiepilogo: gestore di punti5Progetto: Conto bancario semplice
Configurazione del progettoImplementazione del conto8Polimorfismo
Puntatori a funzione nelle structSimulare i metodiIl concetto di interfacciaImplementare le interfacceIterazione polimorficaRiepilogo: Greeter11Pattern di progettazione in C
Pattern SingletonPattern FactoryPattern IteratorRiepilogo: Factory di Logger3Ciclo di vita degli oggetti
Pattern del costruttorePattern del distruttoreInizializzazione sullo stackCopia profondaRiepilogo: wrapper di stringhe6Ereditarietà tramite composizione
Incorporamento delle structLa regola del primo membroAccesso ai membri della classe baseUpcastingRiepilogo: gerarchia di forme9Progetto: Disegnatore di forme
Panoramica del progettoImplementazione del cerchioImplementazione del rettangoloUtilizzo polimorficoContenitore di formeEsercitati da solo: Compilatore C online