Contenu du cours
Pointeurs Intelligents C++
Pointeurs Intelligents C++
Applications Réelles des Pointeurs Intelligents
Les pointeurs intelligents jouent un rôle crucial dans le développement moderne de C++. Ils n'offrent pas seulement une gestion dynamique de la mémoire, mais permettent également une gestion efficace et sécurisée de divers scénarios réels. Explorons quelques applications avancées de std::unique_ptr, std::shared_ptr et std::weak_ptr dans des contextes pratiques.
Pointeurs partagés
Les pointeurs partagés excellent dans tous les domaines où le partage de ressources est nécessaire. Considérez un scénario où plusieurs composants d'un système ont besoin d'accéder à une ressource partagée, comme une connexion à une base de données. Nous pouvons utiliser un pointeur partagé dans ce cas pour une gestion et un nettoyage efficaces de la connexion.
main
#include <memory> #include <iostream> class Database { // Database implementation }; class Component { public: //each component holds a shared pointer to the same resource std::shared_ptr<Database> db_ptr; Component(std::shared_ptr<Database> db) : db_ptr(db) {} // Other component functionalities }; int main() { std::shared_ptr<Database> db = std::make_shared<Database>(); // Different components using the same database Component component1(db); Component component2(db); // Simulate different component usage component1.db_ptr.reset(); // Resets usage in component 1 // component2 still holds a reference to the database }
Dans l'exemple ci-dessus, nous créons une seule ressource de base de données qui est partagée par différents composants. Chaque composant contient un pointeur partagé qui pointe vers la même ressource. C'est un moyen sûr de partager la ressource de la base de données car cela garantit que la base de données reste active tant qu'il y a un pointeur partagé pointant vers elle.
Pointeurs uniques
Si vous gérez certains objets à l'aide d'un conteneur, comme un vecteur, l'implémentation peut être rendue plus robuste en utilisant des pointeurs uniques. Considérez cet exemple :
main
#include <memory> #include <vector> #include <iostream> class Widget { public: ~Widget() { std::cout <<"Widget object destroyed." << std::endl; } }; int main() { std::vector<std::unique_ptr<Widget>> widgetContainer; widgetContainer.push_back(std::make_unique<Widget>()); widgetContainer.push_back(std::make_unique<Widget>()); // Proper cleanup upon container destruction widgetContainer.clear(); // Widgets are automatically deallocated }
Dans notre exemple ci-dessus, nous simulons un vecteur qui contient plusieurs widgets alloués dynamiquement. Étant donné que ces widgets n'ont pas besoin d'être partagés, nous n'avons pas besoin d'un pointeur partagé ici. Tout ce dont nous avons besoin est un pointeur unique qui garantit que chaque widget est correctement désalloué lorsque le vecteur est vidé.
Si vous exécutez le programme ci-dessus, vous verrez le destructeur être automatiquement appelé pour les deux objets widget.
Pointeurs faibles
Dans les structures de données en graphe, les nœuds peuvent se référencer mutuellement, ce qui peut potentiellement conduire à des références cycliques. Nous pouvons utiliser des pointeurs faibles pour rompre ces cycles et éviter les fuites de mémoire.
Dans l'extrait ci-dessus, nous utilisons un pointeur faible pour éviter de créer une référence cyclique dans un graphe. Pour accéder au nœud et effectuer une opération, nous convertissons le pointeur faible en pointeur partagé.
Merci pour vos commentaires !