Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
301112.docx
Скачиваний:
1
Добавлен:
01.03.2025
Размер:
1.95 Mб
Скачать

Int main()

{

using namespace std;

int nights = 1001;

int * pt = new int; // allocate space for an int

*pt = 1001; // store a value there

cout << "nights value = ";

cout << nights << ": location " << &nights << endl;

cout << "int ";

cout << "value = " << *pt << ": location = " << pt << endl;

double * pd = new double;

// allocate space for a double

*pd = 10000001.0; // store a double there

cout << "double ";

cout << "value = " << *pd << ": location = " << pd << endl;

cout << "location of pointer pd: " << &pd << endl;

cout << "size of pt = " << sizeof(pt);

cout << ": size of *pt = " << sizeof(*pt) << endl;

cout << "size of pd = " << sizeof pd;

cout << ": size of *pd = " << sizeof(*pd) << endl;

cin.get();

return 0;

}

Ниже показан вывод программы из листинга 4.17:

Естественно, точные значения адресов памяти будут варьироваться от системы к системе.

Замечания по программе

Программа в листинге 4.17 использует операцию new для выделения памяти под объекты данных типа int и типа double. Это происходит во время выполнения программы. Указатели pt и pd указывают на эти объекты данных. Без них вы не смогли бы получить к ним доступ. С ними же вы можете применять *pt и *pd подобно тому, как вы используете обычные переменные. Вы присваиваете значения новым объектам данных, присваивая их *pt и *pd. Аналогично вы посылаете на печать *pt и *pd, чтобы отобразить эти значения.

Программа в листинге 4.17 также демонстрирует одну из причин того, что необходимо объявить тип данных, на которые указывает указатель. Сам по себе адрес относится только к началу сохраненного объекта, он не включает информации о типе или размере. К тому же обратите внимание, что указатель на int имеет тот же размер, что и указатель на double. Оба они являются адресами. Но поскольку объявлены типы указателей, программа знает, что *pd имеет тип double размером в 8 байт, в то время как *pt представляет собой значение типа int размером в 4 байта. Когда программа печатает значение *pd, cout известно, сколько байт нужно прочитать и как их интерпретировать.

Еще один момент, который следует отметить, состоит в том, что обычно операция new использует другие блоки памяти, чем применяемые ранее объявления обычных переменных.

Освобождение памяти с помощью операции delete

Использование операции new для запрашивания памяти, когда она нужна — одна из сторон пакета управления памятью C++. Второй стороной является операция delete, которая позволяет вернуть память в пул свободной памяти, когда работа с ней завершена. Это — важный шаг к максимально эффективному использованию памяти. Память, которую вы возвращаете, или освобождаете, затем может быть повторно использована другими частями программы. Операция delete применяется с указателем на блок памяти, который был выделен операцией new:

int * ps = new int;

// выделить память с помощью операции new

. // использовать память

delete ps; // по завершении освободить память

// с помощью операции delete

Это освобождает память, на которую указывает ps, но не удаляет сам указатель ps. Вы можете повторно использовать ps — например, чтобы указать на другой выделенный new блок памяти. Вы всегда должны обеспечивать сбалансированное применение new и delete; в противном случае вы рискуете столкнуться с таким явлением, как утечка памяти, т.е. ситуацией, когда память выделена, но более не может быть использована. Если утечки памяти слишком велики, то попытка программы выделить очередной блок может привести к ее аварийному завершению.

Вы не должны пытаться освобождать блок памяти, который уже был однажды освобожден. Стандарт C++ гласит, что результат таких попыток не определен, а это значит, что последствия могут оказаться любыми. Кроме того, вы не можете с помощью операции delete освобождать память, которая была выделена посредством объявления обычных переменных:

Операция delete должна использоваться только для освобождения памяти, выделенной с помощью new.

Обратите внимание, что обязательным условием применения операции delete является использование ее с памятью, выделенной операцией new. Это не значит, что вы обязаны применять тот же указатель, который был использован с new - просто нужно задать тот же адрес:

int * ps = new int; // выделение памяти

int * pq = ps; // установка второго указателя на тот же блок

delete pq; // вызов delete для второго указателя

Обычно не стоит создавать два указателя на один и тот же блок памяти, т.к. это может привести к ошибочной попытке освобождения одного и того же блока дважды. Но, как вы вскоре убедитесь, применение второго указателя оправдано, когда вы работаете с функциями, возвращающими указатель.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]