logo

Älykkäät osoittimet C++:ssa

Edellytys: Osoittimet C++:ssa

Osoittimia käytetään ohjelman ulkopuolisiin resursseihin, kuten kasamuistiin, pääsyyn. Joten keon muistiin pääsyyn (jos keon muistiin luodaan jotain) käytetään osoittimia. Kun käytämme ulkoista resurssia, käytämme vain kopiota resurssista. Jos teemme siihen muutoksia, muutamme vain kopioitua versiota. Mutta jos käytämme osoitinta resurssiin, voimme muuttaa alkuperäistä resurssia.



Ongelmia tavallisten osoittimien kanssa

Jotkut ongelmat normaaleissa osoittimissa C++:ssa ovat seuraavat:

    Muistivuoto: Tämä tapahtuu, kun ohjelma varaa muistia toistuvasti, mutta sitä ei koskaan vapauteta. Tämä johtaa liialliseen muistinkulutukseen ja lopulta järjestelmän kaatumiseen. Roikkuvat osoittimet: Roikkuva osoitin on osoitin, joka esiintyy silloin, kun objektin varaus poistetaan muistista muuttamatta osoittimen arvoa. Villi osoittimet: Villi osoittimet ovat osoittimia, jotka on ilmoitettu ja varattu muistia, mutta osoitinta ei koskaan alusteta osoittamaan mihinkään kelvolliseen objektiin tai osoitteeseen. Tietojen epäjohdonmukaisuus: Tietojen epäjohdonmukaisuutta ilmenee, kun joitakin tietoja on tallennettu muistiin, mutta niitä ei päivitetä johdonmukaisesti. Puskurin ylivuoto: Kun osoitinta käytetään tietojen kirjoittamiseen muistiosoitteeseen, joka on varatun muistilohkon ulkopuolella. Tämä johtaa tietojen vioittumiseen, jota haitalliset hyökkääjät voivat hyödyntää.

Esimerkki:

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

>

>

Lähtö

Memory limit exceeded>

Selitys: Toiminnassa hauskaa , se luo osoittimen, joka osoittaa Suorakulmio esine. Objekti Suorakulmio sisältää kaksi kokonaislukua, pituus, ja leveys . Kun toiminto hauskaa päättyy, p tuhotaan, koska se on paikallinen muuttuja. Mutta sen kuluttamaa muistia ei jaeta, koska unohdimme käyttää poista p; toiminnon lopussa. Tämä tarkoittaa, että muisti ei ole vapaa muiden resurssien käytettäväksi. Mutta emme enää tarvitse muuttujaa, tarvitsemme muistia.

Toiminnassa, pää , hauskaa kutsutaan äärettömässä silmukassa. Se tarkoittaa, että se jatkaa luomistaan s . Se varaa yhä enemmän muistia, mutta ei vapauta niitä, koska emme jakaneet sitä. Hukkaan mentyä muistia ei voi käyttää uudelleen. Mikä on muistivuoto. Koko pino muisti voi tulla hyödyttömäksi tästä syystä.

Älykkäät osoittimet

Kuten olemme tiedostaneet, osoittimen kohdistamatta jättäminen aiheuttaa muistivuodon, joka voi johtaa ohjelman kaatumiseen. Kielet Java, C# on Jätteiden keräysmekanismit käyttää älykkäästi käyttämätöntä muistia käytettäväksi uudelleen. Ohjelmoijan ei tarvitse huolehtia muistivuodoista. C++ keksii oman mekanisminsa Älykäs osoitin . Kun esine tuhoutuu, se vapauttaa myös muistin. Joten meidän ei tarvitse poistaa sitä, koska Smart Pointer käsittelee sen.

A Älykäs osoitin on kääreluokka osoittimen päällä operaattorin kaltaisella operaattorilla * ja -> ylikuormitettu. Älykäs osoitinluokan objektit näyttävät normaaleista osoittimista. Mutta toisin kuin Normaalit osoittimet, se voi purkaa ja vapauttaa tuhoutuneiden objektien muistin.

Ajatuksena on ottaa luokka osoittimella, hävittäjä, ja ylikuormitetut operaattorit kuten * ja -> . Koska tuhoaja kutsutaan automaattisesti, kun objekti menee soveltamisalan ulkopuolelle, dynaamisesti varattu muisti poistetaan automaattisesti (tai viitemäärää voidaan pienentää).

Esimerkki:

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

>

>

Lähtö

20>

Ero osoittimien ja älykkäiden osoittimien välillä

Osoitin

Älykäs osoitin

Osoitin on muuttuja, joka säilyttää muistiosoitteen sekä tietotyyppitiedot kyseisestä muistipaikasta. Osoitin on muuttuja, joka osoittaa jotain muistissa. Se on osoittimen käärittävä pino-allokoitu objekti. Älykkäät osoittimet ovat selkeästi sanottuna luokkia, jotka käärivät osoittimen, tai laajennettuja osoittimia.
Sitä ei tuhota missään muodossa, kun se menee soveltamisalansa ulkopuolelle Se tuhoaa itsensä, kun se menee ulkopuolelle
Osoittimet eivät ole niin tehokkaita, koska ne eivät tue muita ominaisuuksia. Älykkäät osoittimet ovat tehokkaampia, koska niissä on muistinhallinnan lisäominaisuus.
Ne ovat hyvin työvoimakeskeisiä/manuaalisia. Ne ovat luonteeltaan automaattisia/esiohjelmoituja.

Huomautus: Tämä toimii vain int . Joten meidän on luotava älykäs osoitin jokaiselle esineelle? Ei , on ratkaisu, Sapluuna . Alla olevassa koodissa kuten näet T voi olla mitä tahansa tyyppiä.

poista npm-välimuisti

Esimerkki:

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

>

>

Lähtö

20>

Huomautus: Älykkäät osoittimet ovat hyödyllisiä myös resurssien, kuten tiedostokahvojen tai verkkopistokkeiden, hallinnassa.

Älykkäiden osoittimien tyypit

C++-kirjastot tarjoavat seuraavan tyyppisiä älykkäiden osoittimien toteutuksia:

  • auto_ptr
  • ainutlaatuinen_ptr
  • jaettu_ptr
  • heikko_ptr

auto_ptr

Auto_ptr:n avulla voit hallita uusista lausekkeista saatuja objekteja ja poistaa ne, kun itse auto_ptr tuhoutuu. Kun objekti kuvataan auto_ptr:n avulla, se tallentaa osoittimen yhteen varattuun objektiin.

Huomautus: Tämä luokkamalli on vanhentunut C++11:stä lähtien. unique_ptr on uusi laitos, jolla on samanlaiset toiminnot, mutta parannettu tietoturva.

ainutlaatuinen_ptr

ainutlaatuinen_ptr tallentaa vain yhden osoittimen. Voimme määrittää toisen kohteen poistamalla nykyisen objektin osoittimesta.

Ainutlaatuiset osoittimet C++:ssa

Esimerkki:

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

>

>

Lähtö

50 50>

jaettu_ptr

Käyttämällä jaettu_ptr useampi kuin yksi osoitin voi osoittaa tähän yhteen kohteeseen kerrallaan ja se säilyttää a Viitelaskuri käyttämällä use_count() menetelmä.

Jaettu osoitin C++:ssa

C++


polku asetettu javassa



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

>

>

Lähtö

50 50 50 2>

heikko_ptr

Weak_ptr on älykäs osoitin, joka sisältää ei-omistavan viittauksen objektiin. Se on paljon samanlainen kuin share_ptr, paitsi että se ei ylläpidä a Viitelaskuri . Tässä tapauksessa osoittimella ei ole tukikohtaa objektissa. Syynä on se, että jos osoittimet pitävät objektia ja pyytävät muita objekteja, ne voivat muodostaa a Umpikuja.

Heikko osoitin C++:ssa

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

>

>

Lähtö

50 1>

C++-kirjastot tarjoavat älykkäiden osoittimien toteutuksia muodossa auto_ptr, yksilöllinen_ptr, jaettu_ptr ja heikko_ptr.