Освой самостоятельно С++ за 21 день.
Шрифт:
1: unsigned short int * pPointer = new unsigned short int;
2: *pPointer = 72;
3: pPointer = new unsigned short int;
4: *pPointer = 84;
В этом случае память, выделенная под переменную, корректно освобождается (строка 3).
Примечание:Каждый раз, когда в программе используется оператор new, за ним должен следовать оператор delete. Очень важно следить,
Размещение объектов в области динамической памяти
Аналогично созданию указателя на целочисленный тип, можно динамически размещать в памяти любые объекты. Например, если вы объявили объект класса Cat, для манипулирования этим объектом можно создать указатель, в котором будет храниться его адрес, — ситуация, абсолютно аналогичная размещению переменных в стеке. Синтаксис этой операции такой же, как и для целочисленных типов:
Cat *pCat = new Cat;
В данном случае использование оператора new вызывает конструктор класса по умолчанию, т.е. конструктор, использующийся без параметров. Важно помнить, что при создании объекта класса конструктор вызывается всегда, независимо от того, размещается объект в стеке или в области динамического обмена.
Удаление объектов
При использовании оператора delete, за которым следует идентификатор указателя на объект, вызывается деструктор соответствующего класса. Это происходит еще до освобождения памяти и возвращения ее в область динамического обмена. В деструкторе, как правило, освобождается вся память, занимаемая объектом класса. Пример динамического размещения и удаления объектов показан в листинге 8.5.
Листинг 8.5. Размещение и удаление объектов в области динамического обмена
1: // Листинг 8.5.
2: // Размещение и удаление объектов в области динамического обмена
3:
4: #include <iostream.h>
5:
6: class SimpleCat
7: {
8: public:
9: SimpleCat;
10: ~SimpleCat;
11: private:
12: int itsAge;
13: };
14:
15: SimpleCat::SimpleCat
16: {
17: cout << "Constructor called.\n";
18: itsAge = 1;
19: }
20:
21: SimpleCat::~SimpleCat
22: {
23: cout << "Destructor called.\n";
24: }
25:
26: int main
27: {
28: cout << "SimpleCat Frisky...\n";
29: SimpleCat Frisky;
30: cout << "SimpleCat *pRags = new SimpleCat...\n";
31: SimpleCat * pRags = new SimpleCat;
32: cout << "delete pRags...\n";
33: delete pRags;
34: cout << "Exiting, watch Frisky go...\n";
35: return 0;
36: }
Результат:
SimpleCat Frisky...
Constructor called.
SimpleCat *pRags = new SimpleCat..
Constructor called.
delete pRags...
Destructor called.
Exiting, watch Frisky go...
Destructor called.
Анализ: В строках 6—13 приведено описанИе простейшего класса SimpleCat. Описание конструктора класса находится в строке 9, а его тело — в строках 15-19. Деструктор описан в строке 10, его тело — в строках 21-24.
В строке 29 создается экземпляр описанного класса, который размешается в стеке. При этом происходит неявный вызов конструктора класса SimpleCat. Второй объект класса создается в строке 31. Для его хранения динамически выделяется память и адрес записывается в указатель pRags. В этом случае также вызывается конструктор. Деструктор класса SimpleCat вызывается в строке 33 как результат применения оператора delete к указателю pRags. При выходе из функции переменная Frisky оказывается за пределами области видимости и для нее также вызывается деструктор.
Доступ к членам класса
Для локальных переменных, являющихся объектами класса, доступ к членам класса осуществляется с помощью оператора прямого доступа (.). Для экземпляров класса, созданных динамически, оператор прямого доступа применяется для объектов, полученных разыменованием указателя. Например, для вызова функции-члена GetAge нужно написать:
(*pRags).GetAge;
Скобки указывают на то, что оператор разыменования должен выполняться еще до вызова функции GetAge.
Такая конструкция может оказаться достаточно громоздкой. Решить эту проблему позволяет специальный оператор косвенного обращения к члену класса, по написанию напоминающий стрелку (->). Для набора этого оператора используется непрерывная последовательность двух символов: тире и знака "больше". В C++ эти символы рассматриваются как один оператор. Листинг 8.6 иллюстрирует пример обращения к переменным и функциям класса, экземпляр которого размещен в области динамического обмена.
Листинг 8.6. Доступ к данным объекта в области динамического обмена
1: // Листинг 8.6.
2: // Доступ к данным объекта в области динамического обмена
3:
4: #include <iostream.h>
5:
6: class SimpleCat
7: {
8: public:
9: SimpleCat { itsAge = 2; }
10: ~SimpleCat { }
11: int GetAge const { return itsAge; >
12: void SetAge(int age) { itsAge = age; }
13: private:
14: int itsAge;
15: };
16:
17: int main
18: {
19: SimpleCat * Frisky = new SimpleCat;