Contenu du cours
Pointeurs Intelligents C++
Pointeurs Intelligents C++
Fournir des Destructeurs Personnalisés pour les Pointeurs Intelligents
Nous savons déjà que les pointeurs intelligents peuvent automatiquement appeler les destructeurs des objets dynamiques lorsque les objets ne sont plus nécessaires. Mais que se passe-t-il si nous voulons appeler une fonction différente pour détruire un objet dynamique et nettoyer correctement la mémoire allouée ? C'est là que les destructeurs personnalisés entrent en jeu.
Qu'est-ce que les destructeurs personnalisés ?
Un destructeur personnalisé est une fonction ou un objet fonction qui est associé à un pointeur intelligent lors de sa création. Il définit comment l'objet pointé doit être détruit lorsque le pointeur intelligent sort de la portée. Les destructeurs personnalisés permettent un contrôle plus granulaire du processus de nettoyage des ressources. Ce comportement permet aux développeurs de désallouer efficacement la mémoire pour une large gamme de ressources, y compris les descripteurs de fichiers, les connexions et les structures de données personnalisées.
Cas d'utilisation pratiques
Considérons un exemple pratique pour comprendre l'importance des destructeurs personnalisés. Supposons que vous travaillez sur un projet qui implique la gestion de fichiers avec des pointeurs intelligents. Vous voulez vous assurer que lorsqu'un pointeur intelligent sort de la portée, il ferme également le fichier associé. Cela garantira deux choses : la mémoire dynamique est désallouée ET le fichier est correctement fermé en même temps. Voici comment nous pouvons faire les deux avec un destructeur personnalisé :
main
#include <iostream> #include <memory> #include <fstream> void customFileDeleter(std::ofstream* file) { //check if file object is accessible and file is open if (file && file->is_open()) { file->close(); // Close the file } delete file; // Release memory } int main() { // Creating a smart pointer to a file with a custom deleter std::unique_ptr<std::ofstream, decltype(&customFileDeleter)> filePtr(new std::ofstream("example.txt"), &customFileDeleter); if (filePtr->is_open()) { *filePtr << "Writing to the file using a smart pointer with a custom deleter!\n"; } else { std::cout << "Failed to open the file!\n"; } // Smart pointer automatically closes the file when it goes out of scope }
Lors de la création du pointeur unique, nous passons la fonction customFileDeleter
, notre destructeur personnalisé, en tant que paramètre de modèle. Le mot-clé decltype
est simplement utilisé pour extraire le type de la fonction au moment de la compilation. La fonction customFileDeleter
nous permet de combiner la désallocation de mémoire et la fermeture de fichier dans une seule fonction.
Pointeurs partagés et destructeurs personnalisés
Pour associer un destructeur personnalisé à un pointeur partagé, nous devons passer le destructeur au constructeur du pointeur partagé. Regardons un exemple simple :
main
#include <iostream> #include <memory> // Custom deleter function for a resource void customResourceDeleter(int* ptr) { std::cout << "Custom deleter called for resource at address: " << ptr << std::endl; delete ptr; } int main() { // Creating a shared pointer with a custom deleter std::shared_ptr<int> sharedPtrWithCustomDeleter(new int(42), customResourceDeleter); // Accessing the shared resource std::cout << "Shared pointer value: " << *sharedPtrWithCustomDeleter << std::endl; // The shared pointer automatically manages the resource using the custom deleter }
Dans l'exemple ci-dessus, nous créons un pointeur partagé vers un entier et passons la fonction de destructeur personnalisé comme argument au constructeur.
Merci pour vos commentaires !