Predpogoj: Kazalci v C++
Kazalci se uporabljajo za dostop do virov, ki so zunanji glede na program – kot je pomnilnik kopice. Torej, za dostop do pomnilnika kopice (če je karkoli ustvarjeno znotraj pomnilnika kopice) se uporabljajo kazalci. Pri dostopu do katerega koli zunanjega vira uporabljamo le kopijo vira. Če ga kaj spreminjamo, ga spremenimo samo v kopirani različici. Če pa uporabimo kazalec na vir, bomo lahko spremenili izvirni vir.
Težave z običajnimi kazalci
Nekatere težave z običajnimi kazalci v C++ so naslednje:
- Puščanje pomnilnika: Do tega pride, ko program večkrat dodeli pomnilnik, vendar ga nikoli ne sprosti. To vodi do prekomerne porabe pomnilnika in sčasoma do zrušitve sistema. Viseči kazalci: Viseči kazalec je kazalec, ki se pojavi v trenutku, ko se objekt odstrani iz pomnilnika, ne da bi se spremenila vrednost kazalca. Divji kazalci: divji kazalci so kazalci, ki so deklarirani in jim je dodeljen pomnilnik, vendar se kazalec nikoli ne inicializira, da kaže na kateri koli veljaven objekt ali naslov. Neskladnost podatkov: Neskladnost podatkov se pojavi, ko so nekateri podatki shranjeni v pomnilniku, vendar niso posodobljeni na dosleden način. Prekoračitev medpomnilnika: Ko se kazalec uporabi za pisanje podatkov na pomnilniški naslov, ki je zunaj dodeljenega pomnilniškega bloka. To vodi do poškodovanja podatkov, ki jih lahko zlonamerni napadalci izkoristijo.
primer:
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();> >}> }> |
>
>
Izhod
Memory limit exceeded>
Pojasnilo: V funkciji zabavno , ustvari kazalec, ki kaže na Pravokotnik predmet. Objekt Pravokotnik vsebuje dve celi števili, dolžina, in širina . Ko funkcija zabavno konča, bo p uničen, ker je lokalna spremenljivka. Toda pomnilnik, ki ga je porabil, ne bo sprostil, ker smo ga pozabili uporabiti izbriši p; na koncu funkcije. To pomeni, da pomnilnik ne bo prost za uporabo z drugimi viri. Vendar ne potrebujemo več spremenljivke, potrebujemo pomnilnik.
V funkciji, glavni , zabavno se kliče v neskončni zanki. To pomeni, da bo še naprej ustvarjal str . Dodeljeval bo vedno več pomnilnika, vendar jih ne bo sprostil, ker ga nismo sprostili. Porabljenega pomnilnika ni mogoče ponovno uporabiti. Kar je uhajanje spomina. Celoten kup pomnilnik lahko iz tega razloga postane neuporaben.
Pametni kazalci
Kot vemo, nezavedno nezavedno sprostitev kazalca povzroči uhajanje pomnilnika, kar lahko povzroči zrušitev programa. Jezika Java, C# ima Mehanizmi za zbiranje smeti za pametno sprostitev neuporabljenega pomnilnika za ponovno uporabo. Programerju ni treba skrbeti za uhajanje pomnilnika. C++ ima svoj mehanizem, ki je Pametni kazalec . Ko je predmet uničen, se sprosti tudi spomin. Torej nam ga ni treba izbrisati, saj ga bo obravnaval Smart Pointer.
A Pametni kazalec je ovojni razred nad kazalcem z operatorjem kot je * in -> preobremenjeni. Objekti razreda pametnega kazalca izgledajo kot običajni kazalci. Toda za razliko od Normalni kazalci, lahko sprosti in sprosti pomnilnik uničenega predmeta.
Ideja je, da se poučujemo s kazalcem, uničevalec, in preobremenjeni operaterji, kot je * in -> . Ker se destruktor samodejno pokliče, ko gre objekt izven obsega, se dinamično dodeljeni pomnilnik samodejno izbriše (ali pa se število sklicev lahko zmanjša).
primer:
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;> }> |
>
>Izhod
20>
Razlika med kazalci in pametnimi kazalci
| Kazalec | Pametni kazalec |
|---|---|
| Kazalec je spremenljivka, ki vzdržuje pomnilniški naslov in podatke o vrsti podatkov o tej pomnilniški lokaciji. Kazalec je spremenljivka, ki kaže na nekaj v pomnilniku. | To je objekt, dodeljen skladu, ki ovija kazalec. Pametni kazalci, preprosto povedano, so razredi, ki ovijajo kazalec, ali kazalci v obsegu. |
| Ne uniči se v nobeni obliki, ko gre izven svojega obsega | Samo sebe uniči, ko gre izven svojega obsega |
| Kazalci niso tako učinkoviti, saj ne podpirajo nobene druge funkcije. | Pametni kazalci so učinkovitejši, saj imajo dodatno funkcijo upravljanja pomnilnika. |
| So zelo osredotočeni na delo/ročnike. | Po naravi so samodejni/predprogramirani. |
Opomba: To deluje samo za int . Torej bomo morali ustvariti pametni kazalec za vsak predmet? št , obstaja rešitev, Predloga . V spodnji kodi, kot lahko vidite T lahko katere koli vrste.
pretvori niz v enum
primer:
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;> }> |
>
>Izhod
20>
Opomba: Pametni kazalci so uporabni tudi pri upravljanju virov, kot so ročaji datotek ali omrežne vtičnice.
Vrste pametnih kazalcev
Knjižnice C++ zagotavljajo implementacije pametnih kazalcev v naslednjih vrstah:
- auto_ptr
- edinstven_ptr
- skupni_ptr
- šibki_ptr
auto_ptr
Z uporabo auto_ptr lahko upravljate objekte, pridobljene iz novih izrazov, in jih izbrišete, ko je sam auto_ptr uničen. Ko je objekt opisan prek auto_ptr, shrani kazalec na en sam dodeljen objekt.
Opomba: Ta predloga razreda je zastarela od C++11. unique_ptr je nov objekt s podobno funkcionalnostjo, vendar z izboljšano varnostjo.
edinstven_ptr
edinstven_ptr shrani samo en kazalec. Drug predmet lahko dodelimo tako, da trenutni objekt odstranimo s kazalca.
primer:
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; }> |
>
>Izhod
50 50>
skupni_ptr
Z uporabo skupni_ptr več kot en kazalec lahko naenkrat kaže na ta predmet in ohranil bo a Referenčni števec uporabljati use_count() metoda.

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; }> |
>
>Izhod
50 50 50 2>
šibki_ptr
Weak_ptr je pameten kazalec, ki vsebuje nelastniški sklic na predmet. Je veliko bolj podoben shared_ptr, le da ne vzdržuje a Referenčni števec . V tem primeru kazalec ne bo imel trdnjave na objektu. Razlog je, če predpostavimo, da kazalci držijo objekt in zahtevajo druge objekte, potem lahko tvorijo a Zastoj.

C++
tat polna oblika
// 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; }> |
>
>Izhod
50 1>
Knjižnice C++ zagotavljajo implementacije pametnih kazalcev v obliki auto_ptr, unique_ptr, shared_ptr in weak_ptr