#include
#include // включите это, чтобы использовать std::unique_ptr
using namespace std;
3:
class Date
{
private:
int Day;
int Month;
int Year;
string DatelnString;
1 2 :
public:
// Конструктор, инициализирующий объект днем, месяцем и годом
Date (int InputDay, int InputMonth, int InputYear)
: Day (InputDay), Mopt.h (InputMonth), Year (InputYear) {};
void DisplayDate()
{
2 0
|
:
|
cout « Day « " / " « Month « " / " « Year « endl;
|
2 1 :
|
}
|
2 2 :
|
};
|
23:
|
|
int main()
{
unique_ptr pDynamicAllocInteger(new int);
*pDynamicAllocInteger = 42;
28:
// Использование интеллектуального указателя как типа int*
cout « "Integer value is: " « *pDynamicAllocInteger « endl;
unique_ptr pHoliday (new Date(25, 11, 2011));
cout « "The new instance of date contains: ";
34:
// Использование pHoliday точно как Date*
pHoliday->DisplayDate();
37:
// При использовании unique_ptr вследующем нет необходимости:
// delete pDynamicAllocInteger;
// delete pHoliday;
41:
return 0;
}
310 ЗАНЯТИЕ 12. Типы операторов и их перегрузка
Результат
Integer value is: 42
The new instance of date contains: 25 / 11 / 2011
Анализ
строке 26 объявляется интеллектуальный указатель типа i n t . Эта строка демонстри рует синтаксис инициализации шаблона для класса интеллектуального указателя u n iq u e _ p t r . Точно так же в строке 32 объявляется интеллектуальный указатель на экземпляр клас са D ate . Пока сосредоточьтесь на шаблоне и игнорируйте детали.
ПРИМЕЧАНИЕ
Не волнуйтесь, если синтаксис шаблона кажется пока непонятным, поскольку
шаблоны рассматриваются позже, на занятии 14, "Макросы и шаблоны”.
Этот пример демонстрирует не только то, как интеллектуальный указатель позволяет использовать обычный синтаксис указателя (строки 30 и 36). В строке 30 вы в состоянии отобразить значение типа i n t , используя синтаксис * p D y n a m ic A llo c In te g e r, тогда как в строке 36 вы используете вызов p H o lid a y - > D is p la y D a ta (), как будто этими двумя переменными были i n t * и D ate* соответственно. Секрет — в классе интеллектуального указателя s t d : :u n iq u e _ p tr , реализующего операторы (*) и (->). Листинг 12.4 является реализацией простого класса интеллектуального указателя.
ЛИСТИНГ 12.4. Реализация операторов (*) и (->) в простом классе интеллектуального указателя_______________
#include
using namespace std;
2 :
template ctypename T>
class smart_pointer
{
private:
T* m_pRawPointer;
public:
smart_pointer (T* pData) : m_pRawPointer (pData) {}
Конструктор
10: ~smart_pointer () {delete m_pRawPointer ;} // Деструктор
1 1 :
T& operator* () const // оператор обращения к значению
{
return * (m_pRawPointer);
}
16:
T* operator-> () const // оператор обращения к члену класса
{
return m_pRawPointer;
20: }
21: };
22
class Date
private:
int Day, Month, Year;
1":string DatelnString;
public:
// Конструктор, инициализирующий объект днем, месяцем и годом
Date (int InputDay, int InputMonth, int InputYear)
: Day (InputDay), Month (InputMonth), Year (InputYear) {};
void DisplayDate()
{
26:
cout << Day «
"/"«
Month << " / " << Year << endl;
2 ":
}
43: int main()
smart_pointer pDynamicInt(new int (42));
cout « "Dynamically allocated integer value = " « *pDynamicInt;
5smart_pointer pDate(new Date(25, 12, 2011));
cout « "Date is = ";
pDate->DisplayDate();
return 0;
Результат
Dynamically allocated integer value = 42
Date is = 25 / 12 / 2011
Анализ
Это версия листинга 12.3, в которой использован собственный класс s m a r t _ p o in te r , определенный в строках 3-24. Поскольку используется синтаксис объявления шаблона, интеллектуальный указатель можно настроить так, чтобы он указывал на любой тип, будь то i n t , как показано в строке 45, или D ate, как показано в строке 48. Наш класс интеллек туального указателя содержит закрытый член типа, на который он указывает, объявленный на строке 7. По существу, класс интеллектуального указателя стремится автоматизировать управление ресурсом, на который указывает этот член класса, включая его автоматическое освобождение в деструкторе, как показано в строке 10. Этот деструктор гарантирует, что, даже после вызова оператора new, вы не обязаны вызывать оператор d e l e t e для освобож дения ресурса памяти вручную, и это не приводит к утечке памяти. Сосредоточьтесь на реализации оператора * в строках 12-15, который возвращает тип Т& (т.е. ссылку на тип, для которого этот шаблон специализируется). Реализация возвращает ссылку на экземпляр (строка 14). Аналогично оператор -> , как показано в строках 17-20, возвращает тип Т* (т.е. указатель типа, для которого этот шаблон специализируется). Реализация оператора
> в строке 19 возвращает указатель на член класса. Вместе эти два оператора гарантиру ют, что класс s m a r t _ p o in te r абстрагирует управление памятью простого указателя и по зволяет использовать функциональные возможности обычного указателя, делая его таким образом интеллектуальным указателем.
312 ЗАНЯТИЕ 12. Типы операторов и их перегрузка
ПРИМЕЧАНИЕ
Классы интеллектуального указателя способны на много большее, чем имита ция обычных указателей или освобождение памяти, когда они выходят из об
ласти видимости. Более подробная информация по этой теме приведена на за нятии 26, “Понятие интеллектуальных указателей”.
Если применение указателя unique_ptr в листинге 12.3 заинтересовало вас, то, чтобы понять его внутреннее устройство, найдите его реализацию в файле заголовка , предоставляемом вашим компилятором или интегриро ванной средой разработки.
Do'stlaringiz bilan baham: |