Необхідна умова: Покажчики в 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++ 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++ 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++ 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