Išmaniosios rodyklės C++
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.
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>>> |