Розумні покажчики. Автоматичний покажчик. Клас auto_ptr
Перед використанням даної теми рекомендується ознайомитись з наступною темою:
Зміст
- 1. Необхідність у використанні розумних покажчиків. Коректне створення та звільнення ресурсу
- 2. Клас auto_ptr. Автоматичний покажчик
- 3. Приклад, що демонструє використання покажчика auto_ptr
- Споріднені теми
Пошук на інших ресурсах:
1. Необхідність у використанні розумних покажчиків. Коректне створення та звільнення ресурсу
У мові C++ робота з ресурсами (файлами, пам’яттю) виконується на основі наступних тверджень. При виділенні пам’яті під ресурс відбувається ініціалізація. Тобто, створюється покажчик, який вказує на ресурс. При завершенні програми ресурс потрібно звільнити. У випадку з файлом, цей файл потрібно закрити. У випадку з виділеною пам’яттю цю пам’ять потрібно звільнити.
Однак, можлива ситуація, коли процес виконання програми не дійде до моменту звільнення ресурсу. Це може бути випадок, коли при виконанні програми виникне виключна ситуація. У цьому випадку ресурс залишиться не звільненим. Нижченаведений код демонструє цю ситуацію для файлового ресурсу.
... void main() { // 1. Оголосити покажчик на ресурс FILE* fp; // Покажчик на ресурс // 2. Спроба відкриття файлу if (!(fp = fopen("myFile.txt", "r"))) { // якщо файл не відкрито, тоді вихід return; } // 3. Якщо файл відкрито, то виконується робота з файлом // ... // Тут може виникнути виключення і файл не буде закрито // !!! // 4. Закриття файлу, якщо програма дійде до цього коду fclose(fp); }
У вищенаведеному коді у п.3 може виникнути виключна ситуація. У результаті файл не буде закрито. Це є небажано.
Рішення проблеми. Щоб розв’язати дану проблему, потрібно створити спеціальний клас, який буде містити наступні складові:
- конструктор, в якому ініціалізується ресурс. У нашому випадку, у конструкторі відкривається файл;
- деструктор, в якому ресурс звільнюється. У нашому випадку відбувається закриття файлу.
Після створення класу потрібно створити об’єкт цього класу, в якому ресурс (файл) буде автоматично створюватись.
Якщо у програмі виникне виключення, відбудеться звільнення об’єкту класу що призведе до виклику деструктора і, відповідно, звільнення ресурсу.
У найбільш спрощеному вигляді для файлового ресурсу цей спеціальний клас має вигляд
... class InputFile { private: ifstream* p; // покажчик на потік вводу public: // Конструктор, в якому створюється ресурс InputFile(const char* filename) { // Ініціалізація ресурсу p = new ifstream(filename); if (!(*p)) { return; } } // Деструктор ~InputFile() { p->close(); } // Інші елементи класу // ... };
За вищенаведеним зразком можна створювати власні класи.
Подібні випадки можуть зустрічатись і для операцій з пам’яттю коли відбувається її виділення та звільнення. У мові C++ є спеціальний клас auto_ptr (automatic pointer – автоматичний покажчик), який забезпечує коректну роботу з будь-якими покажчиками, що вказують на виділений фрагмент пам’яті.
⇑
2. Клас auto_ptr. Автоматичний покажчик
Клас auto_ptr призначений для роботи з об’єктами, для яких потрібно виконувати виділення та звільнення пам’яті з допомогою оператора new. Клас розміщується в просторі імен std.
При роботі з покажчиком типу auto_ptr можна працювати як зі звичайним покажчиком, який вказує на динамічний об’єкт, що був створений оператором new. При завершенні програми, пам’ять що виділена під динамічний об’єкт, буде звільнена у деструкторі класу auto_ptr.
Оголошення класу має вигляд
class std::auto_ptr<T>;
тут T – тип об’єкту, на який вказує покажчик.
Створення об’єкту класу auto_ptr може виконуватись в один з двох нижченаведених способів
auto_ptr<T> p; auto_ptr<T> p(pT);
тут
- p – екземпляр типу автоматичного покажчика auto_ptr;
- T – тип, на який вказує екземпляр p;
- pT – покажчик, який вказує на тип T. Цей покажчик містить значення адреси пам’яті, яка була виділена оператором new.
Клас auto_ptr містить дві функції:
T* get() const; T* release();
тут T – тип об’єкту, на який вказує покажчик auto_ptr.
Метод get() повертає покажчик на об’єкт типу T.
Метод release() повертає покажчик на об’єкт типу T, але при цьому забирає у покажчика auto_ptr права володіння на цей об’єкт. Сам об’єкт не знищується.
⇑
3. Приклад, що демонструє використання покажчика auto_ptr
Нижче наводиться демонстраційна програма, в якій використовується покажчик типу auto_ptr. У програмі демонструється використання:
- оператора = при присвоєнні покажчиків;
- методу get();
- методу release().
#include <iostream> using namespace std; void main() { // Покажчик типу auto_ptr // 1. Оголошення покажчика p1, який вказує на число 10 auto_ptr<int> p1(new int(10)); cout << "*p1 = " << *p1 << endl; // *p1 = 10 // 2. Оголошення покажчика p2, який поки що рівний nullptr auto_ptr<int> p2; // 3. Присвоєння покажчиків // При присвоєнні пам'ять виділена для p1 звільняється, // а для p2 виділяється або іншими словами: // ресурс звільняється і ресурс виділяється p2 = p1; // після цього p1=nullptr, значення переходить в p2 cout << "*p2 = " << *p2 << endl; // *p2 = 10 // cout << *p1 << endl; // помилка, тому що для p1 пам'ять вже звільнена // 4. Метод get() - повернути звичайний покажчик // без передачі права володіння int* pI1; pI1 = p2.get(); cout << "*pI1 = " << *pI1 << endl; // 10 cout << "*p2 = " << *p2 << endl; // 10, покажчик p2 також вказує на 10 // 5. Метод release() - отримати покажчик з передачею права володіння int* pI2; pI2 = p2.release(); // pI2=>10, p2=>nullptr cout << "*pI2 = " << *pI2 << endl; // 10 // Перевірка значення p2 if (p2.get() == nullptr) cout << "p2==nullptr" << endl; // + else cout << "p2!=nullptr" << endl; }
Результат виконання програми
*p1 = 10 *p2 = 10 *pI1 = 10 *p2 = 10 *pI2 = 10 p2==nullptr
⇑
Споріднені теми
- Розумні покажчики. Класи покажчиків unique_ptr, shared_ptr, weak_ptr
- Загальні поняття. Типи покажчиків. Керовані та некеровані покажчики. Покажчик на функцію. Приклади використання
⇑