logo

Розумні покажчики в C++

Необхідна умова: Покажчики в C++

Покажчики використовуються для доступу до зовнішніх по відношенню до програми ресурсів, як-от купа пам’яті. Отже, для доступу до пам’яті купи (якщо щось створюється в пам’яті купи) використовуються покажчики. Під час доступу до будь-якого зовнішнього ресурсу ми просто використовуємо копію ресурсу. Якщо ми вносимо в нього будь-які зміни, ми просто змінюємо його в скопійованій версії. Але якщо ми використовуємо вказівник на ресурс, ми зможемо змінити вихідний ресурс.



Проблеми зі звичайними покажчиками

Деякі проблеми зі звичайними покажчиками в C++ такі:

    Витік пам’яті: це відбувається, коли програма постійно виділяє пам’ять, але ніколи не звільняється. Це призводить до надмірного споживання пам’яті та зрештою призводить до збою системи. Висячі вказівники: висячий вказівник — це вказівник, який виникає під час вилучення об’єкта з пам’яті без зміни значення вказівника. Дикі покажчики: дикі покажчики — це покажчики, які оголошуються та виділяють пам’ять, але вказівник ніколи не ініціалізується, щоб вказувати на будь-який дійсний об’єкт або адресу. Неузгодженість даних: невідповідність даних виникає, коли деякі дані зберігаються в пам’яті, але не оновлюються узгоджено. Переповнення буфера: коли вказівник використовується для запису даних на адресу пам’яті, яка знаходиться за межами виділеного блоку пам’яті. Це призводить до пошкодження даних, якими можуть скористатися зловмисники.

приклад:

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

>

>

Вихід

Memory limit exceeded>

Пояснення: У функції веселощі , він створює вказівник, який вказує на Прямокутник об'єкт. Об'єкт Прямокутник містить два цілих числа, довжина, і ширина . Коли функція веселощі закінчується, p буде знищено, оскільки це локальна змінна. Але пам’ять, яку він спожив, не буде звільнено, оскільки ми забули використати її видалити p; в кінці функції. Це означає, що пам’ять не буде вільною для використання іншими ресурсами. Але нам більше не потрібна змінна, нам потрібна пам’ять.

У функції, основний , веселощі викликається в нескінченному циклі. Це означає, що він продовжить створювати стор . Він виділятиме все більше пам’яті, але не звільнить їх, оскільки ми не звільняли її. Витрачену пам’ять не можна використовувати знову. Що є витоком пам'яті. Все купа пам'ять може стати марною з цієї причини.

Розумні покажчики

Як ми знаємо, несвідоме невилучення вказівника викликає витік пам’яті, що може призвести до збою програми. Є мови Java, C# Механізми збору сміття щоб розумно звільнити невикористану пам’ять для повторного використання. Програмісту не потрібно турбуватися про витоки пам’яті. C++ пропонує власний механізм Розумний покажчик . Коли об'єкт знищується, він також звільняє пам'ять. Отже, нам не потрібно його видаляти, оскільки Smart Pointer впорається з цим.

А Розумний покажчик є класом-огорткою над вказівником з оператором like * і -> перевантажений. Об'єкти класу розумних покажчиків виглядають як звичайні покажчики. Але, на відміну від Звичайні покажчики, він може звільнити пам'ять знищеного об'єкта.

Ідея полягає в тому, щоб взяти урок з указкою, руйнівник, і перевантажені оператори, як * і -> . Оскільки деструктор викликається автоматично, коли об’єкт виходить за межі області видимості, динамічно виділена пам’ять буде автоматично видалена (або кількість посилань може бути зменшена).

приклад:

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

>

>

Вихід

20>

Різниця між покажчиками та розумними покажчиками

покажчик

Розумний покажчик

Покажчик — це змінна, яка зберігає адресу пам’яті, а також інформацію про тип даних про цю ділянку пам’яті. Покажчик — це змінна, яка вказує на щось у пам’яті. Це виділений стеком об’єкт, що обертає покажчик. Простими словами, розумні покажчики — це класи, які обертають покажчик, або покажчики з областю видимості.
Він не знищується в будь-якій формі, коли виходить за межі своєї сфери Він руйнує сам себе, коли виходить за межі його дії
Покажчики не настільки ефективні, оскільки вони не підтримують жодної іншої функції. Розумні покажчики більш ефективні, оскільки мають додаткову функцію керування пам’яттю.
Вони дуже орієнтовані на працю/ручну роботу. Вони є автоматичними/попередньо запрограмованими за своєю природою.

Примітка: Це працює лише для внутр . Отже, нам доведеться створити Smart Pointer для кожного об’єкта? Немає , є рішення, Шаблон . У коді нижче, як ви бачите Т може бути будь-якого типу.

bash довжина рядка

приклад:

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

>

>

Вихід

20>

Примітка: Розумні вказівники також корисні в управлінні ресурсами, такими як дескриптори файлів або мережеві сокети.

Типи розумних покажчиків

Бібліотеки C++ забезпечують реалізації інтелектуальних покажчиків таких типів:

  • auto_ptr
  • унікальний_ptr
  • shared_ptr
  • слабкий_ptr

auto_ptr

Використовуючи auto_ptr, ви можете керувати об’єктами, отриманими з нових виразів, і видаляти їх, коли сам auto_ptr буде знищено. Коли об’єкт описується через auto_ptr, він зберігає покажчик на один виділений об’єкт.

Примітка: Цей шаблон класу застарів із C++11. unique_ptr — це новий засіб зі схожою функціональністю, але з покращеним захистом.

унікальний_ptr

унікальний_ptr зберігає лише один покажчик. Ми можемо призначити інший об’єкт, видаливши поточний об’єкт із покажчика.

Унікальні покажчики в C++

приклад:

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

>

>

Вихід

50 50>

shared_ptr

З допомогою shared_ptr більше ніж один вказівник може вказувати на цей один об’єкт одночасно, і він підтримуватиме a Лічильник посилань використовуючи use_count() метод.

Спільний покажчик у 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; }>

>

порівняти в рядку
>

Вихід

50 50 50 2>

слабкий_ptr

Weak_ptr — це розумний вказівник, який містить невласне посилання на об’єкт. Він набагато більше схожий на shared_ptr, за винятком того, що він не підтримує a Лічильник посилань . У цьому випадку вказівник не матиме опори на об’єкт. Причина полягає в тому, що якщо припустимо, що покажчики тримають об’єкт і запитують інші об’єкти, вони можуть сформувати a Тупикова ситуація.

Слабкий покажчик у 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; }>

>

>

Вихід

50 1>

Бібліотеки C++ забезпечують реалізацію розумних покажчиків у формі auto_ptr, unique_ptr, shared_ptr і weak_ptr