Būtina sąlyga: Rodyklės C++
Rodyklės naudojamos norint pasiekti išorinius programos išteklius, pvz., krūvos atmintį. Taigi, norint pasiekti krūvos atmintį (jei kas nors sukurta krūvos atmintyje), naudojamos rodyklės. Pasiekdami bet kokį išorinį šaltinį naudojame tik jo kopiją. Jei atliekame kokius nors pakeitimus, tiesiog pakeisime nukopijuotą versiją. Bet jei naudosime žymeklį į išteklius, galėsime pakeisti pradinį šaltinį.
Problemos su įprastomis rodyklėmis
Kai kurios problemos, susijusios su įprastomis C++ rodyklėmis, yra šios:
- Atminties nutekėjimas: atsitinka, kai programa pakartotinai skiria atmintį, bet niekada neatlaisvina. Dėl to sunaudojama per daug atminties ir galiausiai sugenda sistema. Kabantys rodyklės: kabantis rodyklė yra rodyklė, atsirandanti tuo metu, kai objektas yra pašalinamas iš atminties, nekeičiant rodyklės reikšmės. Laukinės rodyklės: Laukinės rodyklės yra žymės, kurios deklaruojamos ir kurioms skiriama atmintis, tačiau žymeklis niekada nėra inicijuojamas, kad būtų nukreiptas į bet kokį tinkamą objektą ar adresą. Duomenų nenuoseklumas: duomenų nenuoseklumas atsiranda, kai kai kurie duomenys saugomi atmintyje, bet nėra nuosekliai atnaujinami. Buferio perpildymas: kai žymeklis naudojamas duomenims įrašyti į atminties adresą, kuris yra už paskirto atminties bloko ribų. Dėl to sugadinami duomenys, kuriais gali pasinaudoti kenkėjiški užpuolikai.
Pavyzdys:
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();> >}> }> |
>
>
Išvestis
Memory limit exceeded>
Paaiškinimas: Funkcijoje linksma , sukuriamas žymeklis, nukreipiantis į Stačiakampis objektas. Objektas Stačiakampis yra du sveikieji skaičiai, ilgis, ir plotis . Kai funkcija linksma baigiasi, p bus sunaikintas, nes tai yra vietinis kintamasis. Tačiau sunaudota atmintis nebus išskirstyta, nes pamiršome ją panaudoti ištrinti p; funkcijos pabaigoje. Tai reiškia, kad atmintis nebus laisvai naudojama kitiems ištekliams. Tačiau mums nebereikia kintamojo, mums reikia atminties.
Veikdamas, pagrindinis , linksma vadinamas begaliniu ciklu. Tai reiškia, kad ji ir toliau kurs p . Ji paskirs vis daugiau atminties, bet jos neatlaisvins, nes mes jos nepaskirstėme. Išeikvota atmintis negali būti naudojama dar kartą. Tai yra atminties nutekėjimas. Visas krūva atmintis gali tapti nenaudinga dėl šios priežasties.
Išmanieji rodyklės
Kaip žinome, nesąmoningai nepašalinus žymeklio atsiranda atminties nutekėjimas, dėl kurio gali sugesti programa. Kalbos Java, C# turi Šiukšlių surinkimo mechanizmai protingai paskirstyti nepanaudotą atmintį, kad ją būtų galima panaudoti dar kartą. Programuotojas neturi jaudintis dėl atminties nutekėjimo. C++ pateikia savo mechanizmą Išmanusis rodyklė . Kai objektas sunaikinamas, jis taip pat išlaisvina atmintį. Taigi, mums nereikia jo ištrinti, nes „Smart Pointer“ tai tvarkys.
A Išmanusis rodyklė yra įvyniojimo klasė virš žymeklio su operatoriumi kaip * ir -> perkrautas. Išmaniųjų rodyklių klasės objektai atrodo kaip įprasti rodyklės. Tačiau, skirtingai nei Įprastos rodyklės, jis gali panaikinti ir atlaisvinti sunaikinto objekto atmintį.
Idėja yra vesti klasę su žymekliu, naikintojas, ir perkrauti operatoriai mėgsta * ir -> . Kadangi naikintojas automatiškai iškviečiamas, kai objektas nepatenka į taikymo sritį, dinamiškai paskirstyta atmintis bus automatiškai ištrinta (arba nuorodų skaičius gali būti sumažintas).
Pavyzdys:
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;> }> |
>
>Išvestis
20>
Skirtumas tarp rodyklių ir išmaniųjų rodyklių
| Rodyklė | Išmanusis rodyklė |
|---|---|
| Rodyklė yra kintamasis, kuris palaiko atminties adresą ir duomenų tipo informaciją apie tą atminties vietą. Rodyklė yra kintamasis, nurodantis ką nors atmintyje. | Tai žymeklį apvyniojantis kamino priskirtas objektas. Išmaniosios rodyklės, paprastai tariant, yra klasės, apvyniojančios žymeklį, arba apimtos rodyklės. |
| Jis nesunaikinamas jokia forma, kai išeina iš savo taikymo srities | Jis sunaikina save, kai išeina iš savo taikymo srities |
| Rodyklės nėra tokios veiksmingos, nes nepalaiko jokios kitos funkcijos. | Išmaniosios rodyklės yra efektyvesnės, nes turi papildomą atminties valdymo funkciją. |
| Jie yra labai orientuoti į darbą / rankiniai. | Jie yra automatiniai / iš anksto užprogramuoti. |
Pastaba: Tai veikia tik tarpt . Taigi, kiekvienam objektui turėsime sukurti išmanųjį žymeklį? Nr , yra sprendimas, Šablonas . Žemiau esančiame kode, kaip matote T gali būti bet kokio tipo.
Linux paleisti cmd
Pavyzdys:
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>>> >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;> }> |
>
>Išvestis
20>
Pastaba: Išmaniosios rodyklės taip pat naudingos valdant išteklius, pvz., failų rankenas ar tinklo lizdus.
Išmaniųjų rodyklių tipai
C++ bibliotekose įdiegtos šių tipų išmaniosios rodyklės:
- auto_ptr
- unikalus_ptr
- Shared_ptr
- silpnas_ptr
auto_ptr
Naudodami auto_ptr galite tvarkyti objektus, gautus iš naujų išraiškų, ir ištrinti juos, kai sunaikinamas pats auto_ptr. Kai objektas aprašomas naudojant auto_ptr, jis išsaugo žymeklį į vieną paskirtą objektą.
Pastaba: Šis klasės šablonas nebenaudojamas nuo C++11. unikalus_ptr yra naujas įrenginys su panašiomis funkcijomis, bet su patobulinta sauga.
unikalus_ptr
unikalus_ptr saugo tik vieną žymeklį. Mes galime priskirti kitą objektą, pašalindami esamą objektą iš žymeklio.
Pavyzdys:
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; }> |
nulis tikrinimas java
>
>Išvestis
50 50>
Shared_ptr
Naudojant Shared_ptr daugiau nei vienas žymeklis vienu metu gali nurodyti šį vieną objektą ir jis išlaikys a Nuorodų skaitiklis naudojant use_count() metodas.

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; }> |
>
>Išvestis
50 50 50 2>
silpnas_ptr
Weak_ptr yra išmanioji rodyklė, turinti nepriklausančią nuorodą į objektą. Jis daug panašesnis į share_ptr, išskyrus tai, kad nepalaikys a Nuorodų skaitiklis . Tokiu atveju rodyklė neturės tvirtovės objekte. Priežastis ta, kad jei rodyklės laiko objektą ir prašo kitų objektų, jie gali sudaryti a Aklavietė.

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; }> |
>
>Išvestis
50 1>
C++ bibliotekose įdiegtos išmaniosios rodyklės auto_ptr, unikalus_ptr, shared_ptr ir silpnas_ptr pavidalu