logo

Inteligentní ukazatele v C++

Předpoklad: Ukazatele v C++

Ukazatele se používají pro přístup ke zdrojům, které jsou externí vůči programu – jako je haldová paměť. Takže pro přístup k paměti haldy (pokud je něco vytvořeno v paměti haldy) se používají ukazatele. Při přístupu k jakémukoli externímu zdroji používáme pouze kopii zdroje. Pokud v něm provedeme nějaké změny, změníme ho pouze v zkopírované verzi. Pokud však použijeme ukazatel na zdroj, budeme moci změnit původní zdroj.



Problémy s normálními ukazateli

Některé problémy s normálními ukazateli v C++ jsou následující:

    Netěsnosti paměti: K tomu dochází, když je paměť opakovaně alokována programem, ale nikdy není uvolněna. To vede k nadměrné spotřebě paměti a nakonec vede ke zhroucení systému. Visící ukazatele: Visutý ukazatel je ukazatel, ke kterému dochází v době, kdy je objekt uvolněn z paměti, aniž by se změnila hodnota ukazatele. Divoké ukazatele: Divoké ukazatele jsou ukazatele, které jsou deklarovány a přiděleny paměti, ale ukazatel není nikdy inicializován, aby ukazoval na jakýkoli platný objekt nebo adresu. Nekonzistence dat: Nekonzistence dat nastává, když jsou některá data uložena v paměti, ale nejsou aktualizována konzistentním způsobem. Přetečení vyrovnávací paměti: Když se ukazatel používá k zápisu dat na adresu paměti, která je mimo alokovaný paměťový blok. To vede k poškození dat, která mohou zneužít zákeřní útočníci.

Příklad:

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

>

>

Výstup

Memory limit exceeded>

Vysvětlení: Ve funkci zábava , vytvoří ukazatel, který ukazuje na Obdélník objekt. Objekt Obdélník obsahuje dvě celá čísla, délka, a šířka . Když funkce zábava skončí, p bude zničen, protože jde o lokální proměnnou. Paměť, kterou spotřebovala, však nebude uvolněna, protože jsme ji zapomněli použít odstranit p; na konci funkce. To znamená, že paměť nebude volná pro použití jinými zdroji. Ale už nepotřebujeme proměnnou, potřebujeme paměť.

ve funkci, hlavní , zábava se volá v nekonečné smyčce. To znamená, že bude tvořit dál p . Bude alokovat stále více paměti, ale neuvolní je, protože jsme ji nepřidělili. Promarněnou paměť nelze znovu použít. Což je únik paměti. Celá halda paměť může být z tohoto důvodu nepoužitelná.

Inteligentní ukazatele

Jak jsme věděli, nevědomé neudělení ukazatele způsobí únik paměti, který může vést ke zhroucení programu. Jazyky Java, C# má Mechanismy sběru odpadků chytře uvolnit nevyužitou paměť k opětovnému použití. Programátor se nemusí obávat žádných úniků paměti. C++ přichází s vlastním mechanismem, který je Chytrý ukazatel . Když je objekt zničen, uvolní se také paměť. Nemusíme to tedy mazat, protože to zvládne Smart Pointer.

A Chytrý ukazatel je třída obalu nad ukazatelem s operátorem jako * a -> přetížené. Objekty třídy inteligentních ukazatelů vypadají jako normální ukazatele. Ale na rozdíl od Normální ukazatele, může uvolnit a uvolnit paměť zničených objektů.

Cílem je vzít třídu s ukazatelem, ničitel, a přetížení operátoři jako * a -> . Vzhledem k tomu, že destruktor je automaticky volán, když objekt překročí rozsah, dynamicky alokovaná paměť bude automaticky odstraněna (nebo může být snížen počet odkazů).

Příklad:

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

>

>

Výstup

20>

Rozdíl mezi ukazateli a inteligentními ukazateli

Ukazatel

Chytrý ukazatel

Ukazatel je proměnná, která udržuje adresu paměti a také informace o datovém typu o tomto umístění v paměti. Ukazatel je proměnná, která ukazuje na něco v paměti. Jedná se o objekt alokovaný do zásobníku. Inteligentní ukazatele, jednoduše řečeno, jsou třídy, které obalují ukazatel nebo ukazatele s rozsahem.
Není zničena v žádné formě, když se dostane mimo její rozsah Zničí se, když se dostane mimo svůj rozsah
Ukazatele nejsou tak efektivní, protože nepodporují žádnou jinou funkci. Inteligentní ukazatele jsou efektivnější, protože mají další funkci správy paměti.
Jsou velmi pracovně/manuální. Jsou svou povahou automatické/předprogramované.

Poznámka: Toto funguje pouze pro int . Takže budeme muset vytvořit Smart Ukazatel pro každý objekt? Ne , existuje řešení, Šablona . V kódu níže, jak vidíte T může být jakéhokoli typu.

modifikační klávesy

Příklad:

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

>

>

Výstup

20>

Poznámka: Inteligentní ukazatele jsou také užitečné při správě zdrojů, jako jsou popisovače souborů nebo síťové zásuvky.

Typy inteligentních ukazatelů

Knihovny C++ poskytují implementace inteligentních ukazatelů v následujících typech:

  • auto_ptr
  • unique_ptr
  • shared_ptr
  • slabý_ptr

auto_ptr

Pomocí auto_ptr můžete spravovat objekty získané z nových výrazů a mazat je, když je auto_ptr zničeno. Když je objekt popsán pomocí auto_ptr, ukládá ukazatel na jeden přidělený objekt.

Poznámka: Tato šablona třídy je od C++11 zastaralá. unique_ptr je nové zařízení s podobnou funkčností, ale s vylepšeným zabezpečením.

unique_ptr

unique_ptr ukládá pouze jeden ukazatel. Jiný objekt můžeme přiřadit odstraněním aktuálního objektu z ukazatele.

Unikátní ukazatele v C++

Příklad:

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

>

zpětné volání peklo v javascriptu

>

Výstup

50 50>

shared_ptr

Používáním shared_ptr více než jeden ukazatel může ukazovat na tento jeden objekt najednou a bude udržovat a Referenční počítadlo za použití use_count() metoda.

Sdílený ukazatel v 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; }>

>

>

Výstup

50 50 50 2>

slabý_ptr

Weak_ptr je inteligentní ukazatel, který obsahuje odkaz na objekt, který nevlastní. Je mnohem podobnější sdílenému_ptr kromě toho, že nebude udržovat a Referenční počítadlo . V tomto případě nebude mít ukazatel na objektu pevnost. Důvodem je, že pokud předpokládejme, že ukazatele drží objekt a požadují další objekty, mohou tvořit a Zablokování.

Slabý ukazatel v 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; }>

>

>

Výstup

50 1>

Knihovny C++ poskytují implementace inteligentních ukazatelů ve formě auto_ptr, unique_ptr, shared_ptr a slabé_ptr