Voorwaarde: Aanwijzers in C++
Pointers worden gebruikt voor toegang tot bronnen die extern zijn aan het programma, zoals heap-geheugen. Voor toegang tot het heap-geheugen (als er iets in het heap-geheugen wordt aangemaakt) worden dus pointers gebruikt. Bij toegang tot een externe bron gebruiken we alleen een kopie van de bron. Als we er wijzigingen in aanbrengen, veranderen we het gewoon in de gekopieerde versie. Maar als we een verwijzing naar de bron gebruiken, kunnen we de oorspronkelijke bron wijzigen.
Problemen met normale wijzers
Enkele problemen met normale verwijzingen in C++ zijn als volgt:
- Geheugenlekken: Dit gebeurt wanneer geheugen herhaaldelijk door een programma wordt toegewezen, maar nooit wordt vrijgegeven. Dit leidt tot overmatig geheugengebruik en uiteindelijk tot een systeemcrash. Dangling Pointers: Een bungelende pointer is een pointer die optreedt op het moment dat de toewijzing van het object uit het geheugen wordt opgeheven zonder de waarde van de pointer te wijzigen. Wild Pointers: Wild pointers zijn pointers die worden gedeclareerd en toegewezen aan geheugen, maar de pointer wordt nooit geïnitialiseerd om naar een geldig object of adres te verwijzen. Gegevensinconsistentie: Gegevensinconsistentie treedt op wanneer bepaalde gegevens in het geheugen zijn opgeslagen, maar niet op een consistente manier worden bijgewerkt. Bufferoverflow: wanneer een pointer wordt gebruikt om gegevens te schrijven naar een geheugenadres dat zich buiten het toegewezen geheugenblok bevindt. Dit leidt tot corruptie van gegevens die kunnen worden misbruikt door kwaadwillende aanvallers.
Voorbeeld:
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();> >}> }> |
>
>
Uitvoer
Memory limit exceeded>
Uitleg: In functie plezier , creëert het een pointer die naar de Rechthoek voorwerp. Het object Rechthoek bevat twee gehele getallen, lengte, En breedte . Wanneer de functie plezier eindigt, wordt p vernietigd omdat het een lokale variabele is. Maar het geheugen dat het verbruikte, wordt niet ongedaan gemaakt omdat we het zijn vergeten te gebruiken verwijder p; aan het einde van de functie. Dat betekent dat het geheugen niet vrij zal zijn om door andere bronnen te worden gebruikt. Maar we hebben de variabele niet meer nodig, we hebben het geheugen nodig.
In functie, voornaamst , plezier wordt aangeroepen in een oneindige lus. Dat betekent dat het blijft creëren P . Het zal steeds meer geheugen toewijzen, maar zal het niet vrijgeven omdat we de toewijzing ervan niet ongedaan hebben gemaakt. Het geheugen dat verloren gaat, kan niet opnieuw worden gebruikt. Wat een geheugenlek is. De hele hoop geheugen kan om deze reden nutteloos worden.
Slimme wijzers
Zoals we onbewust weten, veroorzaakt het niet ongedaan maken van de toewijzing van een aanwijzer een geheugenlek dat kan leiden tot een crash van het programma. Talen Java, C# heeft Mechanismen voor het verzamelen van afval om op slimme wijze ongebruikt geheugen vrij te maken zodat het opnieuw kan worden gebruikt. De programmeur hoeft zich geen zorgen te maken over geheugenlekken. C++ komt met zijn eigen mechanisme Slimme aanwijzer . Wanneer het object wordt vernietigd, wordt ook het geheugen vrijgemaakt. We hoeven het dus niet te verwijderen, omdat Smart Pointer het afhandelt.
A Slimme aanwijzer is een wrapper-klasse over een pointer met een operator zoals * En -> overbelast. De objecten van de slimme pointerklasse zien eruit als normale pointers. Maar niet zoals Normale wijzers, het kan de toewijzing van vernietigde objectgeheugens ongedaan maken en vrijmaken.
Het idee is om een les te volgen met een aanwijzer, torpedojager, en overbelaste operators zoals * En -> . Omdat de destructor automatisch wordt aangeroepen wanneer een object buiten bereik raakt, wordt het dynamisch toegewezen geheugen automatisch verwijderd (of kan het aantal referenties worden verlaagd).
Voorbeeld:
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;> }> |
>
>Uitvoer
20>
Verschil tussen aanwijzers en slimme aanwijzers
| Wijzer | Slimme aanwijzer |
|---|---|
| Een pointer is een variabele die een geheugenadres bijhoudt, evenals gegevenstype-informatie over die geheugenlocatie. Een pointer is een variabele die naar iets in het geheugen verwijst. | Het is een pointer-wrapping stack-allocated object. Slimme pointers zijn, simpel gezegd, klassen die een pointer omsluiten, of scoped pointers. |
| Het wordt in geen enkele vorm vernietigd als het buiten zijn bereik valt | Het vernietigt zichzelf als het buiten zijn bereik valt |
| Aanwijzers zijn niet zo efficiënt omdat ze geen enkele andere functie ondersteunen. | Slimme wijzers zijn efficiënter omdat ze een extra functie van geheugenbeheer hebben. |
| Ze zijn erg arbeidsgericht/handmatig. | Ze zijn automatisch/voorgeprogrammeerd van aard. |
Opmerking: Dit werkt alleen voor int . We moeten dus voor elk object een Smart Pointer maken? Nee , er is een oplossing, Sjabloon . In de onderstaande code zoals je kunt zien T kan van elk type zijn.
hoe verborgen dingen op Android te vinden
Voorbeeld:
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;> }> |
>
>Uitvoer
20>
Opmerking: Slimme pointers zijn ook nuttig bij het beheer van bronnen, zoals bestandsingangen of netwerksockets.
Soorten slimme aanwijzers
C++-bibliotheken bieden implementaties van slimme pointers in de volgende typen:
- auto_ptr
- unieke_ptr
- gedeelde_ptr
- zwakke_ptr
auto_ptr
Met auto_ptr kunt u objecten beheren die zijn verkregen uit nieuwe expressies en deze verwijderen wanneer auto_ptr zelf wordt vernietigd. Wanneer een object wordt beschreven via auto_ptr, wordt er een verwijzing naar een enkel toegewezen object opgeslagen.
Opmerking: Deze klassensjabloon is verouderd vanaf C++11. unique_ptr is een nieuwe faciliteit met een vergelijkbare functionaliteit, maar met verbeterde beveiliging.
unieke_ptr
unieke_ptr slaat slechts één aanwijzer op. We kunnen een ander object toewijzen door het huidige object van de aanwijzer te verwijderen.
Voorbeeld:
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; }> |
>
>Uitvoer
50 50>
gedeelde_ptr
Door het gebruiken van gedeelde_ptr meer dan één aanwijzer kan naar dit ene object tegelijk verwijzen en het zal een Referentieteller de ... gebruiken gebruik_count() methode.

C++
tekenreeks formaat
// 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; }> |
>
>Uitvoer
50 50 50 2>
zwakke_ptr
Weak_ptr is een slimme aanwijzer die een niet-eigen verwijzing naar een object bevat. Het lijkt veel meer op shared_ptr, behalve dat het geen Referentieteller . In dit geval zal een aanwijzer geen bolwerk op het object hebben. De reden hiervoor is dat als de pointers het object vasthouden en om andere objecten vragen, ze een 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; }> |
>
>Uitvoer
50 1>
C++-bibliotheken bieden implementaties van slimme pointers in de vorm van auto_ptr, unique_ptr, shared_ptr en weekly_ptr