Règle de trois : si une classe gère une ressource (par exemple, la mémoire), toute implémentation explicite de l'un des méthodes suivants nécessite l'implémentation des autres :
C++11 : Règle de cinq – des opérations de déplacement ont été ajoutées :
La violation de cette règle entraîne des erreurs de gestion des ressources, telles que la suppression double ou les fuites de mémoire.
class Buffer { char* data; public: Buffer(size_t sz) : data(new char[sz]) {} ~Buffer() { delete[] data; } Buffer(const Buffer& other) : data(new char[strlen(other.data)+1]) { strcpy(data, other.data); } Buffer& operator=(const Buffer& other) { if (&other != this) { delete[] data; data = new char[strlen(other.data)+1]; strcpy(data, other.data); } return *this; } // sémantique de mouvement en C++11+ : Buffer(Buffer&& other) noexcept : data(other.data) { other.data = nullptr; } Buffer& operator=(Buffer&& other) noexcept { if (&other != this) { delete[] data; data = other.data; other.data = nullptr; } return *this; } };
Est-il suffisant d'implémenter uniquement le destructeur si la classe gère un pointeur ?
Non. Sans opérations de copie et de déplacement, une copie entraînera une suppression double de la mémoire. Par exemple :
Buffer a(10); Buffer b = a; // b et a vont supprimer le même pointeur !
Histoire
Dans la plateforme d'agrégation de données pour les télécommunications, toutes les classes ne prenaient en compte que le destructeur. Après le refactoring des structures, il y a eu une chute massive due à des suppressions doubles : la copie des objets produisait des comportements aléatoires.
Histoire
Dans un projet de jeu mobile, ils ont oublié d'implémenter le constructeur de déplacement pour la classe de conteneur de tampon. Lors du déplacement, l'objet était copié, ce qui entraînait des copies de données supplémentaires et une baisse de performance.
Histoire
Dans une bibliothèque de sérialisation des structures de données, lors du retour d'un objet depuis une fonction, un objet temporaire était retourné, et le constructeur de copie réalisait une copie superficielle du pointeur. Cela a entraîné de nombreuses fuites, qui n'ont été détectées qu'après des mois de fonctionnement.