FAQ C++Consultez toutes les FAQ
Nombre d'auteurs : 34, nombre de questions : 368, dernière mise à jour : 14 novembre 2021 Ajouter une question
Cette FAQ a été réalisée à partir des questions fréquemment posées sur les forums de http://www.developpez.com et de l'expérience personnelle des auteurs.
Je tiens à souligner que cette FAQ ne garantit en aucun cas que les informations qu'elle propose sont correctes ; les auteurs font le maximum, mais l'erreur est humaine. Cette FAQ ne prétend pas non plus être complète. Si vous trouvez une erreur ou si vous souhaitez devenir rédacteur, lisez ceci.
Sur ce, nous vous souhaitons une bonne lecture.
Toute mémoire allouée dans vos programmes avec new doit être libérée à un moment ou un autre avec delete. Cette bonne règle de programmation peut vite devenir contraignante et parfois difficile à mettre en œuvre dans la pratique.
Les pointeurs intelligents (smart pointers en anglais) sont des objets se comportant comme des pointeurs classiques (mimétisme dans la syntaxe et certaines sémantiques), mais qui offrent en plus des fonctionnalités intéressantes permettant une gestion quasi automatique de la mémoire (en particulier de sa libération). Leur syntaxe est très proche de celle des pointeurs classiques (grâce à la surcharge des opérateurs *, ->, etc.), mais ils utilisent en interne divers mécanismes (comptage de références) qui permettent de déceler qu'un objet n'est plus utilisé, auquel cas le pointeur intelligent se charge de le détruire ce qui permet d'éviter les fuites de mémoire.
Utiliser des pointeurs intelligents est généralement une très bonne idée, en particulier lors de l'écriture de code susceptible d'être interrompu par des exceptions (soit presque tout le temps !). Si tel est le cas, ceux-ci ne manqueront pas de libérer la mémoire qui leur est associée lors de leur destruction (suite à une exception ou non), ce qu'il n'est pas possible d'assurer sans multiplier les blocs try...catch dans son code.
Code c++ : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | // Test1 est exception safe sans utilisation de pointeur intelligent void Test1() { int * ptr = new int; try { // code pouvant lever une exception } catch ( ... ) // gestion approximative... { // libérer le pointeur delete ptr; // relancer l'exception throw; } // tout s'est bien passé, libérer la mémoire delete ptr; } |
Code c++ : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 | #include <memory> // pour std::unique_ptr // Test2 est exception safe en utilisant un pointeur intelligent void Test2() { // std::unique_ptr est la classe pointeur intelligent standard std::unique_ptr<int> smart_ptr = std::make_unique<int>(); // code pouvant lever une exception (rien d'autre !) } |
Cependant attention, les pointeurs intelligents n'échappent pas à la règle que ce qui a été alloué avec new doit être libéré avec delete et ce qui a été alloué avec new [] doit l'être avec delete []. Or std::unique_ptr<T> tout comme std::shared_ptr<T> appellent par défaut l'opérateur delete. Pour gérer des tableaux, vous devez utiliser std::unique_ptr<T[]> et (disponible seulement depuis C++17, avant il vous faudra fournir un deleter) std::shared_ptr<T[]> afin qu'ils appellent delete[], ou il faudra utiliser une autre classe telle que boost::shared_array. Mais n'oubliez pas que std::vector est là pour éviter ces tracasseries avec les tableaux ce qui fait une bonne raison de plus de l'utiliser à la place des tableaux classiques (lire à ce sujet Comment créer et utiliser un tableau avec std::vector ?).
C++11
Attention, l'utilisation de std::auto_ptr est dépréciée depuis la norme C++11 : vous devriez le remplacer par std::unique_ptr ou std::shared_ptr selon le cas. |
C++03
Il existe un type standard de pointeurs intelligents : std::auto_ptr déclaré dans l'en-tête <memory>. Mais en pratique, son utilisation peut s'avérer problématique si l'on n'a pas pris le temps de bien comprendre son fonctionnement. C'est pourquoi cette classe est souvent déconseillée, surtout aux débutants.
Contrairement à beaucoup de pointeurs intelligents, std::auto_ptr n'utilise pas un mécanisme de comptage de références afin de partager un même objet pointé par plusieurs pointeurs intelligents (l'objet est détruit lorsque plus aucun pointeur ne l'utilise). std::auto_ptr utilise un mécanisme plus simple, mais plus risqué : il n'y a qu'un seul propriétaire de l'objet pointé et ce dernier est détruit lorsque son propriétaire l'est. Si une copie est effectuée d'un auto_ptr vers un autre, il y a transfert de propriété, c'est-à-dire que la possession de l'objet pointé sera transmise du premier au second, et le premier deviendra alors un pointeur invalide (NULL).
Code c++ : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 | int Test() { // ptr1 est le propriétaire std::auto_ptr<int> ptr1( new int ); { // ptr2 devient le propriétaire std::auto_ptr<int> ptr2 = ptr1; } // ici ptr2 est détruit, le int est libéré ! // ptr1 pointe désormais vers NULL *ptr1 = 10; // aïe aïe aïe... } |
Code c++ : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | include <memory> // Ptr est passé par valeur, donc a priori aucun risque que le // paramètre donné lors de l'appel ne soit modifié void Test( std::auto_ptr<MaClasse> Ptr ) { // Mais ce qui va réellement se passer, c'est que Ptr va prendre // le contrôle de l'objet pointé, et le détruire à la fin de la fonction ! } MaClasse* Ptr1 = new MaClasse; Test( std::auto_ptr<MaClasse>( Ptr1 ) ); // Ici Ptr1 ne pointe plus sur une zone valide, il a été détruit suite à l'appel std::auto_ptr<MaClasse> Ptr2( new MaClasse ); Test( Ptr2 ); // Ici Ptr2 ne pointe plus sur la donnée originale // il pointe sur NULL et la donnée a été détruite dans la fonction |
Un autre point important est que std::auto_ptr appelle l'opérateur delete et non delete [] ce qui en interdit l'usage avec des pointeurs retournés par new [] (tableaux).
On peut tout de même envisager de l'utiliser pour rendre une fonction exception-safe à peu de frais, comme cela est expliqué dans la question Qu'est-ce qu'un pointeur intelligent ?.
Mais on préfèrera utiliser les pointeurs intelligents de Boost, par exemple (voir Comment utiliser les pointeurs intelligents de Boost ?).
Proposer une nouvelle réponse sur la FAQ
Ce n'est pas l'endroit pour poser des questions, allez plutôt sur le forum de la rubrique pour çaLes sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2024 Developpez Developpez LLC. Tous droits réservés Developpez LLC. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents et images sans l'autorisation expresse de Developpez LLC. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.