logo

Intelligente Zeiger in C++

Voraussetzung: Zeiger in C++

Zeiger werden für den Zugriff auf Ressourcen verwendet, die außerhalb des Programms liegen – wie z. B. Heap-Speicher. Für den Zugriff auf den Heap-Speicher (falls etwas im Heap-Speicher erstellt wird) werden also Zeiger verwendet. Beim Zugriff auf eine externe Ressource verwenden wir lediglich eine Kopie der Ressource. Wenn wir Änderungen daran vornehmen, ändern wir diese einfach in der kopierten Version. Wenn wir jedoch einen Zeiger auf die Ressource verwenden, können wir die ursprüngliche Ressource ändern.



Probleme mit normalen Zeigern

Einige Probleme mit normalen Zeigern in C++ sind wie folgt:

    Speicherlecks: Dies tritt auf, wenn Speicher von einem Programm wiederholt zugewiesen, aber nie freigegeben wird. Dies führt zu einem übermäßigen Speicherverbrauch und schließlich zu einem Systemabsturz. Dangling Pointer: Ein Dangling Pointer ist ein Zeiger, der zu dem Zeitpunkt auftritt, zu dem die Zuordnung des Objekts aus dem Speicher aufgehoben wird, ohne dass der Wert des Zeigers geändert wird. Wild-Zeiger: Wild-Zeiger sind Zeiger, die deklariert werden und denen Speicher zugewiesen wird, der Zeiger jedoch niemals so initialisiert wird, dass er auf ein gültiges Objekt oder eine gültige Adresse zeigt. Dateninkonsistenz: Dateninkonsistenz tritt auf, wenn einige Daten im Speicher gespeichert sind, aber nicht auf konsistente Weise aktualisiert werden. Pufferüberlauf: Wenn ein Zeiger verwendet wird, um Daten an eine Speicheradresse zu schreiben, die außerhalb des zugewiesenen Speicherblocks liegt. Dies führt zur Beschädigung von Daten, die von böswilligen Angreifern ausgenutzt werden können.

Beispiel:

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();> >}> }>

>

>

Ausgabe

Memory limit exceeded>

Erläuterung: In Funktion Spaß , erstellt es einen Zeiger, der auf die zeigt Rechteck Objekt. Das Objekt Rechteck enthält zwei ganze Zahlen, Länge, Und Breite . Wenn die Funktion Spaß endet, wird p zerstört, da es sich um eine lokale Variable handelt. Der verbrauchte Speicher wird jedoch nicht freigegeben, weil wir vergessen haben, ihn zu verwenden p löschen; am Ende der Funktion. Das bedeutet, dass der Speicher nicht für die Nutzung durch andere Ressourcen frei ist. Aber wir brauchen die Variable nicht mehr, wir brauchen den Speicher.

In Funktion, hauptsächlich , Spaß wird in einer Endlosschleife aufgerufen. Das bedeutet, dass es weiter kreiert P . Dadurch wird immer mehr Speicher zugewiesen, aber nicht freigegeben, da wir die Speicherzuweisung nicht aufgehoben haben. Der verschwendete Speicher kann nicht erneut verwendet werden. Das ist ein Speicherverlust. Das ganze Haufen Der Speicher kann aus diesem Grund unbrauchbar werden.

Intelligente Zeiger

Wie wir wissen, führt die unbewusste Nichtfreigabe eines Zeigers zu einem Speicherverlust, der zum Absturz des Programms führen kann. Sprachen Java, C# hat Garbage-Collection-Mechanismen um nicht genutzten Speicher intelligent freizugeben, um ihn erneut zu verwenden. Der Programmierer muss sich keine Sorgen über Speicherlecks machen. C++ verfügt über einen eigenen Mechanismus Intelligenter Zeiger . Wenn das Objekt zerstört wird, wird auch der Speicher freigegeben. Wir müssen es also nicht löschen, da Smart Pointer damit umgehen wird.

A Intelligenter Zeiger ist eine Wrapper-Klasse über einen Zeiger mit einem Operator wie * Und -> überladen. Die Objekte der Smart-Pointer-Klasse sehen aus wie normale Zeiger. Aber nicht wie Normale Zeiger, Es kann zerstörten Objektspeicher freigeben und freigeben.

Die Idee ist, eine Klasse mit einem Zeiger zu nehmen, Zerstörer, und überlastete Betreiber mögen * Und -> . Da der Destruktor automatisch aufgerufen wird, wenn ein Objekt den Gültigkeitsbereich verlässt, wird der dynamisch zugewiesene Speicher automatisch gelöscht (oder der Referenzzähler kann dekrementiert werden).

Beispiel:

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;> }>

>

>

Ausgabe

20>

Unterschied zwischen Zeigern und intelligenten Zeigern

Zeiger

Intelligenter Zeiger

Ein Zeiger ist eine Variable, die eine Speicheradresse sowie Datentypinformationen zu diesem Speicherort verwaltet. Ein Zeiger ist eine Variable, die auf etwas im Speicher zeigt. Es handelt sich um ein stapelzugewiesenes Objekt mit Zeigerumbruch. Intelligente Zeiger sind im Klartext Klassen, die einen Zeiger umschließen, oder bereichsbezogene Zeiger.
Es wird in keiner Form zerstört, wenn es seinen Geltungsbereich verlässt Es zerstört sich selbst, wenn es seinen Wirkungsbereich verlässt
Zeiger sind nicht so effizient, da sie keine andere Funktion unterstützen. Intelligente Zeiger sind effizienter, da sie über eine zusätzliche Funktion zur Speicherverwaltung verfügen.
Sie sind sehr arbeitsorientiert/manuell. Sie sind automatischer/vorprogrammierter Natur.

Notiz: Dies funktioniert nur für int . Also müssen wir für jedes Objekt einen Smart Pointer erstellen? NEIN , es gibt eine Lösung, Vorlage . Im Code unten, wie Sie sehen können T kann von beliebiger Art sein.

Was ist ein Android-Osterei?

Beispiel:

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;> }>

>

>

Ausgabe

20>

Notiz: Intelligente Zeiger sind auch bei der Verwaltung von Ressourcen wie Dateihandles oder Netzwerk-Sockets nützlich.

Arten von Smart Pointern

C++-Bibliotheken stellen Implementierungen von Smart Pointern in den folgenden Typen bereit:

  • auto_ptr
  • unique_ptr
  • shared_ptr
  • schwacher_ptr

auto_ptr

Mit auto_ptr können Sie aus neuen Ausdrücken erhaltene Objekte verwalten und sie löschen, wenn auto_ptr selbst zerstört wird. Wenn ein Objekt durch auto_ptr beschrieben wird, speichert es einen Zeiger auf ein einzelnes zugewiesenes Objekt.

Notiz: Diese Klassenvorlage ist ab C++11 veraltet. unique_ptr ist eine neue Funktion mit ähnlicher Funktionalität, aber verbesserter Sicherheit.

unique_ptr

unique_ptr speichert nur einen Zeiger. Wir können ein anderes Objekt zuweisen, indem wir das aktuelle Objekt vom Zeiger entfernen.

Eindeutige Zeiger in C++

Beispiel:

C++


np.sum



// 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; }>

>

>

Ausgabe

50 50>

shared_ptr

Durch die Nutzung shared_ptr Es kann mehr als ein Zeiger gleichzeitig auf dieses eine Objekt zeigen und es behält ein Referenzzähler Verwendung der use_count() Methode.

Gemeinsamer Zeiger in C++

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; }>

>

>

Ausgabe

50 50 50 2>

schwacher_ptr

Weak_ptr ist ein intelligenter Zeiger, der einen nicht besitzenden Verweis auf ein Objekt enthält. Es ist shared_ptr viel ähnlicher, außer dass es kein verwaltet Referenzzähler . In diesem Fall hat ein Zeiger keinen Halt auf dem Objekt. Der Grund dafür ist, dass, wenn angenommen wird, dass Zeiger das Objekt halten und andere Objekte anfordern, sie möglicherweise ein Objekt bilden Sackgasse.

Schwacher Zeiger in C++

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; }>

>

>

Ausgabe

50 1>

C++-Bibliotheken stellen Implementierungen intelligenter Zeiger in Form von auto_ptr, unique_ptr, shared_ptr und schwach_ptr bereit