C++ : Les pointeurs intelligents

Comprendre le pointeur unique : unique_ptr

TESTEZ LINKEDIN LEARNING GRATUITEMENT ET SANS ENGAGEMENT

Tester maintenant Afficher tous les abonnements
Prenez en main le pointeur unique. Ce pointeur est destiné à référencer une ressource de façon exclusive.

Transcription

Un pointeur unique est un pointeur qui garantit un accès exclusif à une ressource. C'est-à-dire qu'il empêche toute copie du pointeur et donc nous garantit, à un instant donné, d'être le seul à manipuler cette ressource. Alors pour voir l'utilisation du pointeur unique, Nous allons passer par un exemple qui manipule une classe chaîne, qui est décrite ici dans chaîne.h, avec des constructeurs, un constructeur copie notamment, et un destructeur, des opérateurs d'affectation et de conversion qui ont été redéfinis pour pouvoir afficher facilement notre donnée pour l'opérateur de conversion, et un accesseur val qui permet d'accéder au champ data qui stocke la chaîne de caractères. L'implémentation ici est truffée de logs qui vont nous permettre de suivre au fur et à mesure des créations et destructions de l'instance ou de copie de l'instance, on va pouvoir suivre le cycle de vie de nos objets. Je reviens au main, et si je le lance, on voit la création du pointeur unique a qui est le premier log que je fais et juste après donc la création de ce pointeur, avec un new chaine ("Automne") qui est symbolisé ici par le log chaîne(Automne) aussi et ce new, qui renvoie à une adresse est directement mis dans a, a qui va assurer la protection de cette adresse et donc la protection de l'accès à la ressource. On a maintenant un pointeur unique a, que l'on peut afficher avec le log_PTR qui est là. On va aussi pouvoir créer un pointeur unique par la méthode make_unique qui est une méthode qui existe en C++14, qui est normalement standard, ici j'ai utilisé outils pour que ce soit compatible avec tous les compilateurs puisque tous ne supportent pas encore le standard C++14, et donc j'ai implémenté moi-même le make_unique dans outils, de façon très simple puisque j'ai repris exactement ici le new donc la même méthode que l'on avait pour a. Ici donc pour vous montrer la méthode officielle maintenant en C++14 make_unique, j'ai refait l'équivalent du std, normalement c'est std si j'avais compilateur compatible, std make_unique qui permettrait de faire la même chose. Donc, si je lance maintenant puisque j'ai créé ici Hiver, j'ai bien b qui contient Hiver après cette opération. L'opération suivante est intéressante, c'est : je change la chaîne pointée par a, c'est à dire que mon pointeur unique a, je le redéfinis en faisant un reset et j'appelle new chaine("Printemps") pour créer une nouvelle instance de chaine et remplacer celle qui contenait Automne par a. Qu'est ce qui va se passer pour Automne ? On le voit au travers de l'exemple : Automne est détruit on voit le destructeur ~chaine ici, Automne, donc le destructeur appelé automatiquement lorsqu'on fait un reset sur un pointeur unique, grand avantage, il n'y a pas à penser à libérer la mémoire donc pas de risque de fuite mémoire sur ce pointeur, et après avoir affecté donc Printemps à mon pointeur. Donc a est devenu maintenant un pointeur vers une ressource qui s'appelle Printemps b reste toujours à Hiver puisqu'on ne l'a pas manipulé. Ensuite, donc, on a aussi la possibilité de faire un déplacement donc un déplacement d'un pointeur va me permettre par exemple de transférer la responsabilité de cette ressource, par exemple b a la ressource Hiver, je vais transférer cette responsabilité de ressource à c donc on peut imaginer deux parties de programme l'une qui passe à l'autre la responsabilité d'une ressource et donc c'est c maintenant qui en a la responsabilité. Alors quand je fais ce move, qui est une opération standard dans std, memory, et ben, j'ai dans le move b qui perd la responsabilité il est maintenant à null au moment où je fais le move et Hiver qui gagne la responsabilité de ce pointeur et de cette ressource. On peut bien sûr quand on n'a plus besoin d'une ressource, désinitialiser si on peut dire le pointeur, le reseter en faisant un reset sur a, on peut le faire aussi sur c par exemple qui est le nouveau propriétaire de la ressource qu'avait b auparavant, et donc si je regarde ces deux lignes, on les voit ici, en faisant un reset de a, Printemps qui était la ressource gérée par a est désalloué, on voit le destructeur appelé, et même chose quand on fait le reset sur c. Voilà la façon officielle de libérer, de reseter une ressource. Si on ne l'avait pas fait, tout simplement à la fin de mon bloc, comme mes ressources sont gérées par mes pointeurs uniques, j'aurais eu une libération de mes ressources. On peut essayer notamment avec c, puisque je peux enlever, commenter le reset, et on verra qu'à la fin de mon programme, malgré tout, j'ai quand même Hiver après Fin qui est détruit. Donc une très bonne gestion de la mémoire et aucun risque de fuite mémoire. Dernière chose c'est comment passer un pointeur unique en paramètre à une fonction. J'ai une fonction g à laquelle je veux passer ma ressource pour qu'elle soit manipulée par g, alors peut-être un peu plus haut puisque j'ai encore c, voilà, je veux passer c à g, voilà, ma fonction g ma fonction g je suis tenté de l'écrire comme ceci. Voilà, chaine c par exemple c'est le nom de mon paramètre. Hop *c pour l'afficher. Donc si je veux lancer ça, je vais avoir le problème de la compilation puisque je n'ai pas le droit de copier un pointeur unique y compris pour un passage de paramètre. Il est par valeurs. Pour résoudre ce problème, tout simplement, il faut passer par un passage par références. Et donc là je ne fais aucune copie. Le passage de paramètres est accepté, et j'ai Hiver qui s'affiche bien avant la réinitialisation de c. Le pointeur unique est donc très pratique à utiliser lorsqu'on a une resource à utilisation unique. Si vous avez des ressources qui ont besoin d'être partagées entre différentes parties du programme, il faudra se tourner vers le pointeur intelligent shared pointeur, pointeur partagé, c'est ce que nous allons voir dans la section suivante.

C++ : Les pointeurs intelligents

Utilisez les pointeurs intelligents et gérez efficacement vos ressources et allocations de mémoire en C++. Choisissez le type de pointeur intelligent en fonction de vos besoins.

29 min (9 vidéos)
Aucun commentaire n´est disponible actuellement
 
Logiciel :
Spécial abonnés
Date de parution :24 oct. 2016

Votre formation est disponible en ligne avec option de téléchargement. Bonne nouvelle : vous ne devez pas choisir entre les deux. Dès que vous achetez une formation, vous disposez des deux options de consultation !

Le téléchargement vous permet de consulter la formation hors ligne et offre une interface plus conviviale. Si vous travaillez sur différents ordinateurs ou que vous ne voulez pas regarder la formation en une seule fois, connectez-vous sur cette page pour consulter en ligne les vidéos de la formation. Nous vous souhaitons un excellent apprentissage avec cette formation vidéo.

N'hésitez pas à nous contacter si vous avez des questions !