Che cosa sta succedendo
Quando scrivi T t;
stai creando un oggetto di tipo T
con durata di memorizzazione automatica . Verrà ripulito automaticamente quando esce dal campo di applicazione.
Quando scrivi new T()
stai creando un oggetto di tipo T
con durata di archiviazione dinamica . Non verrà pulito automaticamente.
È necessario passare un puntatore ad esso delete
per ripulirlo:
Tuttavia, il tuo secondo esempio è peggio: stai dereferenziando il puntatore e stai facendo una copia dell'oggetto. In questo modo perdi il puntatore all'oggetto creato con new
, così non potrai mai cancellarlo anche se lo desideri!
Cosa dovresti fare
Dovresti preferire la durata della memorizzazione automatica. Hai bisogno di un nuovo oggetto, basta scrivere:
A a; // a new object of type A
B b; // a new object of type B
Se è necessaria una durata della memoria dinamica, archiviare il puntatore sull'oggetto allocato in un oggetto durata della memoria automatica che lo elimina automaticamente.
template <typename T>
class automatic_pointer {
public:
automatic_pointer(T* pointer) : pointer(pointer) {}
// destructor: gets called upon cleanup
// in this case, we want to use delete
~automatic_pointer() { delete pointer; }
// emulate pointers!
// with this we can write *p
T& operator*() const { return *pointer; }
// and with this we can write p->f()
T* operator->() const { return pointer; }
private:
T* pointer;
// for this example, I'll just forbid copies
// a smarter class could deal with this some other way
automatic_pointer(automatic_pointer const&);
automatic_pointer& operator=(automatic_pointer const&);
};
automatic_pointer<A> a(new A()); // acts like a pointer, but deletes automatically
automatic_pointer<B> b(new B()); // acts like a pointer, but deletes automatically
Questo è un linguaggio comune che va dal nome non molto descrittivo RAII ( Resource Acquisition Is Initialization ). Quando si acquisisce una risorsa che necessita di pulizia, la si inserisce in un oggetto con durata di archiviazione automatica, quindi non è necessario preoccuparsi di ripulirla. Questo vale per qualsiasi risorsa, sia essa memoria, file aperti, connessioni di rete o qualunque cosa tu voglia.
Questo automatic_pointer
cosa esiste già in varie forme, l'ho appena fornita per fare un esempio. Una classe molto simile esiste nella libreria standard chiamata std::unique_ptr
.
Ce n'è anche uno vecchio (pre-C ++ 11) chiamato auto_ptr
ma ora è deprecato perché ha uno strano comportamento di copia.
E poi ci sono alcuni esempi ancora più intelligenti, come std::shared_ptr
, che consente a più puntatori allo stesso oggetto e lo pulisce solo quando l'ultimo puntatore viene distrutto.