Prérequis: Pointeurs en C++
Les pointeurs sont utilisés pour accéder aux ressources externes au programme, comme la mémoire tas. Ainsi, pour accéder à la mémoire tas (si quelque chose est créé dans la mémoire tas), des pointeurs sont utilisés. Lorsque nous accédons à une ressource externe, nous utilisons simplement une copie de la ressource. Si nous y apportons des modifications, nous le modifions simplement dans la version copiée. Mais si nous utilisons un pointeur vers la ressource, nous pourrons modifier la ressource d’origine.
Problèmes avec les pointeurs normaux
Certains problèmes avec les pointeurs normaux en C++ sont les suivants :
- Fuites de mémoire : cela se produit lorsque la mémoire est allouée à plusieurs reprises par un programme mais n'est jamais libérée. Cela conduit à une consommation excessive de mémoire et conduit finalement à un crash du système. Pointeurs suspendus : un pointeur suspendu est un pointeur qui se produit au moment où l'objet est désalloué de la mémoire sans modifier la valeur du pointeur. Pointeurs sauvages : les pointeurs sauvages sont des pointeurs qui sont déclarés et alloués en mémoire, mais le pointeur n'est jamais initialisé pour pointer vers un objet ou une adresse valide. Incohérence des données : une incohérence des données se produit lorsque certaines données sont stockées en mémoire mais ne sont pas mises à jour de manière cohérente. Débordement de tampon : lorsqu'un pointeur est utilisé pour écrire des données sur une adresse mémoire située en dehors du bloc de mémoire alloué. Cela conduit à la corruption des données qui peuvent être exploitées par des attaquants malveillants.
Exemple:
C++
// C++ program to demonstrate working of a Pointers> #include> using> namespace> std;> class> Rectangle {> private>:> >int> length;> >int> breadth;> };> void> fun()> {> >// By taking a pointer p and> >// dynamically creating object> >// of class rectangle> >Rectangle* p =>new> Rectangle();> }> int> main()> {> >// Infinite Loop> >while> (1) {> >fun();> >}> }> |
>
>
Sortir
Memory limit exceeded>
Explication: En fonction amusant , cela crée un pointeur qui pointe vers le Rectangle objet. L'object Rectangle contient deux entiers, longueur, et largeur . Lorsque la fonction amusant se termine, p sera détruit car il s’agit d’une variable locale. Mais la mémoire consommée ne sera pas libérée car nous avons oublié d’utiliser supprimer p ; à la fin de la fonction. Cela signifie que la mémoire ne pourra pas être utilisée par d’autres ressources. Mais nous n’avons plus besoin de la variable, nous avons besoin de la mémoire.
En fonction, principal , amusant est appelé dans une boucle infinie. Cela signifie qu'il continuera à créer p . Cela allouera de plus en plus de mémoire mais ne la libérera pas car nous ne l’avons pas désalloué. La mémoire gaspillée ne peut plus être utilisée. Ce qui est une fuite de mémoire. L'ensemble tas la mémoire peut devenir inutile pour cette raison.
Pointeurs intelligents
Comme nous le savons inconsciemment, ne pas désallouer un pointeur provoque une fuite de mémoire pouvant entraîner un crash du programme. Langages Java, C# ont Mécanismes de collecte des déchets pour libérer intelligemment la mémoire inutilisée afin de la réutiliser. Le programmeur n’a pas à s’inquiéter des fuites de mémoire. C++ propose son propre mécanisme Pointeur intelligent . Lorsque l'objet est détruit, la mémoire est également libérée. Nous n’avons donc pas besoin de le supprimer car Smart Pointer s’en chargera.
UN Pointeur intelligent est une classe wrapper sur un pointeur avec un opérateur comme * et -> surchargé. Les objets de la classe des pointeurs intelligents ressemblent à des pointeurs normaux. Mais contrairement à Pointeurs normaux, il peut désallouer et libérer la mémoire des objets détruits.
L'idée est de suivre un cours avec un pointeur, destructeur, et des opérateurs surchargés comme * et -> . Étant donné que le destructeur est automatiquement appelé lorsqu'un objet sort de la portée, la mémoire allouée dynamiquement sera automatiquement supprimée (ou le nombre de références peut être décrémenté).
Exemple:
C++
// C++ program to demonstrate the working of Smart Pointer> #include> using> namespace> std;> class> SmartPtr {> >int>* ptr;>// Actual pointer> public>:> >// Constructor: Refer> >// techcodeview.com for use of> >// explicit keyword> >explicit> SmartPtr(>int>* p = NULL) { ptr = p; }> >// Destructor> >~SmartPtr() {>delete> (ptr); }> >// Overloading dereferencing operator> >int>& operator*() {>return> *ptr; }> };> int> main()> {> >SmartPtr ptr(>new> int>());> >*ptr = 20;> >cout << *ptr;> >// We don't need to call delete ptr: when the object> >// ptr goes out of scope, the destructor for it is> >// automatically called and destructor does delete ptr.> >return> 0;> }> |
>
>Sortir
20>
Différence entre les pointeurs et les pointeurs intelligents
| Aiguille | Pointeur intelligent |
|---|---|
| Un pointeur est une variable qui conserve une adresse mémoire ainsi que des informations de type de données sur cet emplacement mémoire. Un pointeur est une variable qui pointe vers quelque chose en mémoire. | Il s’agit d’un objet alloué à la pile qui enveloppe le pointeur. En termes simples, les pointeurs intelligents sont des classes qui enveloppent un pointeur ou des pointeurs étendus. |
| Il n’est détruit sous aucune forme lorsqu’il sort de son champ d’application | Il se détruit lorsqu'il sort de son champ d'action |
| Les pointeurs ne sont pas aussi efficaces car ils ne prennent en charge aucune autre fonctionnalité. | Les pointeurs intelligents sont plus efficaces car ils disposent d’une fonctionnalité supplémentaire de gestion de la mémoire. |
| Ils sont très centrés sur le travail/manuels. | Ils sont de nature automatique/préprogrammée. |
Note: Cela ne fonctionne que pour int . Donc, nous devrons créer un pointeur intelligent pour chaque objet ? Non , il y a une solution, Modèle . Dans le code ci-dessous comme vous pouvez le voir T peut être de n’importe quel type.
répertoire dans les commandes Linux
Exemple:
C++
// C++ program to demonstrate the working of Template and> // overcome the issues which we are having with pointers> #include> using> namespace> std;> // A generic smart pointer class> template> <>class> T>>class> SmartPtr {> >T* ptr;>// Actual pointer> public>:> >// Constructor> >explicit> SmartPtr(T* p = NULL) { ptr = p; }> >// Destructor> >~SmartPtr() {>delete> (ptr); }> >// Overloading dereferencing operator> >T& operator*() {>return> *ptr; }> >// Overloading arrow operator so that> >// members of T can be accessed> >// like a pointer (useful if T represents> >// a class or struct or union type)> >T* operator->() {>return> ptr; }> };> int> main()> {> >SmartPtr<>int>>ptr(>new> int>());> >*ptr = 20;> >cout << *ptr;> >return> 0;> }> |
>
>Sortir
20>
Note: Les pointeurs intelligents sont également utiles dans la gestion des ressources, telles que les descripteurs de fichiers ou les sockets réseau.
Types de pointeurs intelligents
Les bibliothèques C++ fournissent des implémentations de pointeurs intelligents dans les types suivants :
- auto_ptr
- unique_ptr
- partagé_ptr
- faible_ptr
auto_ptr
En utilisant auto_ptr, vous pouvez gérer les objets obtenus à partir de nouvelles expressions et les supprimer lorsque auto_ptr lui-même est détruit. Lorsqu'un objet est décrit via auto_ptr, il stocke un pointeur vers un seul objet alloué.
Note: Ce modèle de classe est obsolète depuis C++11. unique_ptr est une nouvelle installation avec une fonctionnalité similaire, mais avec une sécurité améliorée.
unique_ptr
unique_ptr stocke un seul pointeur. Nous pouvons attribuer un objet différent en supprimant l'objet actuel du pointeur.
Exemple:
C++
// C++ program to demonstrate the working of unique_ptr> // Here we are showing the unique_pointer is pointing to P1.> // But, then we remove P1 and assign P2 so the pointer now> // points to P2.> #include> using> namespace> std;> // Dynamic Memory management library> #include> class> Rectangle {> >int> length;> >int> breadth;> public>:> >Rectangle(>int> l,>int> b)> >{> >length = l;> >breadth = b;> >}> >int> area() {>return> length * breadth; }> };> int> main()> {> // --/ Smart Pointer> >unique_ptr P1(>new> Rectangle(10, 5));> >cout // This'll print 50 // unique_ptr P2(P1); unique_ptr P2; P2 = move(P1); // This'll print 50 cout // cout return 0; }> |
>
>
Java lit le fichier CSVSortir
50 50>
partagé_ptr
En utilisant partagé_ptr plusieurs pointeurs peuvent pointer vers cet objet à la fois et il maintiendra un Compteur de référence en utilisant le use_count() méthode.

C++
// C++ program to demonstrate the working of shared_ptr> // Here both smart pointer P1 and P2 are pointing to the> // object Addition to which they both maintain a reference> // of the object> #include> using> namespace> std;> // Dynamic Memory management library> #include> class> Rectangle {> >int> length;> >int> breadth;> public>:> >Rectangle(>int> l,>int> b)> >{> >length = l;> >breadth = b;> >}> >int> area() {>return> length * breadth; }> };> int> main()> {> >//---/ Smart Pointer> >shared_ptr P1(>new> Rectangle(10, 5));> >// This'll print 50> >cout shared_ptr P2; P2 = P1; // This'll print 50 cout // This'll now not give an error, cout // This'll also print 50 now // This'll print 2 as Reference Counter is 2 cout << P1.use_count() << endl; return 0; }> |
>
>Sortir
50 50 50 2>
faible_ptr
Weak_ptr est un pointeur intelligent qui contient une référence non propriétaire à un objet. C'est beaucoup plus similaire à shared_ptr sauf qu'il ne conservera pas de Compteur de référence . Dans ce cas, un pointeur n’aura pas de place forte sur l’objet. La raison est que si nous supposons que les pointeurs détiennent l'objet et demandent d'autres objets, ils peuvent alors former un Impasse.

C++
// C++ program to demonstrate the working of weak_ptr> // Here both smart pointer P1 and P2 are pointing to the> // object Addition to which they both does not maintain> // a reference of the object> #include> using> namespace> std;> // Dynamic Memory management library> #include> class> Rectangle {> >int> length;> >int> breadth;> public>:> >Rectangle(>int> l,>int> b)> >{> >length = l;> >breadth = b;> >}> >int> area() {>return> length * breadth; }> };> int> main()> {> >//---/ Smart Pointer> >shared_ptr P1(>new> Rectangle(10, 5));> > >// create weak ptr> >weak_ptr P2 (P1);> > >// This'll print 50> >cout // This'll print 1 as Reference Counter is 1 cout << P1.use_count() << endl; return 0; }> |
>
>Sortir
50 1>
Les bibliothèques C++ fournissent des implémentations de pointeurs intelligents sous la forme de auto_ptr, unique_ptr, shared_ptr et faible_ptr.