Qu'est-ce qui se passe
Lorsque vous écrivez, T t;
vous créez un objet de type T
avec une durée de stockage automatique . Il sera nettoyé automatiquement lorsqu'il sera hors de portée.
Lorsque vous écrivez, new T()
vous créez un objet de type T
avec une durée de stockage dynamique . Il ne sera pas nettoyé automatiquement.
Vous devez lui passer un pointeur delete
pour le nettoyer:
Cependant, votre deuxième exemple est pire: vous déréférencer le pointeur et faire une copie de l'objet. De cette façon, vous perdez le pointeur vers l'objet créé avec new
, vous ne pouvez donc jamais le supprimer même si vous le souhaitez!
Ce que tu devrais faire
Vous devriez préférer la durée de stockage automatique. Besoin d'un nouvel objet, écrivez simplement:
A a; // a new object of type A
B b; // a new object of type B
Si vous avez besoin d'une durée de stockage dynamique, stockez le pointeur vers l'objet alloué dans un objet de durée de stockage automatique qui le supprime automatiquement.
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
C'est un idiome courant qui porte le nom peu descriptif RAII ( Resource Acquisition Is Initialization ). Lorsque vous acquérez une ressource qui doit être nettoyée, vous la collez dans un objet de durée de stockage automatique afin que vous n'ayez pas à vous soucier de son nettoyage. Cela s'applique à n'importe quelle ressource, que ce soit la mémoire, les fichiers ouverts, les connexions réseau ou tout ce que vous voulez.
Cette automatic_pointer
chose existe déjà sous diverses formes, je viens de la fournir à titre d'exemple. Une classe très similaire existe dans la bibliothèque standard appelée std::unique_ptr
.
Il existe également un ancien (pré-C ++ 11) nommé, auto_ptr
mais il est maintenant obsolète car il a un comportement de copie étrange.
Et puis il y a des exemples encore plus intelligents, comme std::shared_ptr
, qui autorisent plusieurs pointeurs vers le même objet et ne le nettoient que lorsque le dernier pointeur est détruit.