Уроки программирования на Visual C++. Использование свободной памяти в С++

Источник: the-programmer
The_Programmer

 

ИСПОЛЬЗОВАНИЕ ОПЕРАТОРА  new

Оператор C++  new  позволяет вашим программам распределять память во время выполнения. Для использования оператора  new  вам необходимо указать количество байтов памяти, которое требуется программе. Предположим, например, что вашей программе необходим 50-байтный массив. Используя оператор  new,  вы можете заказать эту память, как показано ниже:

char *buffer = new char[50];

Говоря кратко, если оператор  new  успешно выделяет память, он возвращает указатель на начало области этой памяти. В данном случае, поскольку программа распределяет память для хранения массива символов, она присваивает возвращаемый указатель переменной, определенной как указатель на тип  char.  Если оператор  new  не может выделить запрашиваемый вами объем памяти, он возвратит NULL-указатель, который содержит значение 0. Каждый раз, когда ваши программы динамически распределяют память с использованием оператора  new,  они должны проверять возвращаемое оператором  new значение, чтобы определить, не равно ли оно NULL.

Зачем необходимо динамически распределять память с использованием new

Многие программы интенсивно используют массивы для хранения множества значений определенного типа. При проектировании своих программ программисты обычно пытаются объявить массивы с размерами, достаточными для удовлетворения будущих потребностей программы. К сожалению, если случится так, что потребности программы когда-нибудь превысят подобные ожидания программиста, то кому-то придется редактировать и перекомпилировать такую программу.

Вместо редактирования и перекомпилирования программ, которые просто запрашивают память с запасом, вам следует создавать свои программы таким образом, чтобы они распределяли требуемую им память динамически во время выполнения, используя оператор new. В этом случае ваши программы могут адаптировать использование памяти в соответствии с вашими изменившимися потребностями, избавляя вас от необходимости редактировать и перекомпилировать программу.

Например, следующая программа USE_NEW.CPP использует оператор  new для  получения указателя на 100-байтный массив:

#include <iostream.h>

void main(void)

{
   char *pointer = new char[100];
   if (pointer != NULL) cout << "Память успешно выделена" << endl;
   else cout << "Ошибка выделения памяти" << endl;
}

Как видите, программа сразу проверяет значение, присвоенное оператором  new  переменной-указателю. Если указатель содержит значение NULL, значит  new  не смог выделить запрашиваемый объем памяти. Если же указатель содержит не NULL, следовательно, new успешно выделил память и указатель содержит адрес начала блока памяти.

Если new не может удовлетворить запрос на память, он возвратит NULL

При использовании оператора new для выделения памяти может случиться так, что ваш запрос не может быть удовлетворен, поскольку нет достаточного объема свободной памяти. Если оператор new не способен выделить требуемую память, он присваивает указателю значение NULL. Проверяя значение указателя, как показано в предыдущей программе, вы можете определить, был ли удовлетворен запрос на память. Например, следующий оператор использует new для распределения памяти под массив из 500 значений с плавающей точкой:

float *array = new float[100];

Чтобы определить, выделил ли оператор new память, ваша программа должна сравнить значение указателя с NULL, как показано ниже:

if (array != NULL)  cout << "Память выделена успешно" << endl;
else  cout << "new не может выделить память" << endl;

Предыдущая программа использовала оператор  new для  выделения 100 байт памяти. Поскольку эта программа "жестко закодирована" на объем требуемой памяти, возможно, вам потребуется ее редактировать и перекомпилировать, если возникнет необходимость, чтобы программа выделила меньше или больше памяти. Как уже кратко обсуждалось, одна из причин для динамического распределения памяти состоит в том, чтобы избавиться от необходимости редактировать и перекомпилировать программу при изменении требований к объему памяти. Следующая программа ASK_MEM.CPP запрашивает у пользователя количество байт памяти, которое необходимо выделить, и затем распределяет память, используя оператор  new:

#include <iostream.h>

void main(void)

{
   int size;
   char *pointer;
   cout << "Введите размер массива, до 30000: ";
   cin >> size;
   if (size <= 30000)

   {
      pointer = new char[size];
      if (pointer != NULL) cout << "Память выделена успешно" << endl;
      else cout << "Невозможно выделить память" << endl;
   } 
}

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

Следующая программа NOMEMORY.CPP выделяет каждый раз память для 10000 символов до тех пор, пока оператор  new  не сможет больше выделить память из свободной памяти. Другими словами, эта программа удерживает выделенную память, пока не использует всю доступную свободную память. Если программа успешно выделяет память, она извещает об этом сообщением. Если память больше не может быть выделена, программа выводит сообщение об ошибке и завершается:

#include <iostream.h>

void main(void)

{
   char * pointer;
   do

   {
      pointer = new char[10000];
      if (pointer != NULL) cout << "Выделено 10000 байт" << endl;
      else cout << "Больше нет памяти" << endl;
   } while (pointer 1= NULL);
}

Замечание:  Если выработаете в среде MS-DOS, то, возможно, будете удивлены тем, что свободная память исчерпается после того, как программа выделит 64 Кбайт, Большинство работающих в MS-DOS компиляторов  C++  по умолчанию используют малую модель памяти, которая обеспечивает только 64 К6aйm свободной памяти. Аналогично, если вы используете среду MS-DOS, то наибольшая область памяти, к которой могут обратиться ваши программы, может быть ограничена 64Кбайт.

О свободной памяти

Каждый раз при запуске вашей программы компилятор C++ устанавливает отдельную область неиспользуемой памяти, которая называется свободной памятью. Используя оператор new, ваша программа может выделить память из этой свободной памяти во время выполнения. Используя свободную память для распределения требуемой памяти, ваши программы не стеснены фиксированными размерами массивов. Размер свободной памяти может изменяться в зависимости от вашей операционной системы и модели памяти компилятора. Если увеличивается количество динамической памяти, требуемой вашими программами, вам необходимо убедиться, что вас не сдерживают ограничения свободной памяти вашей системы.

ОСВОБОЖДЕНИЕ ПАМЯТИ, ЕСЛИ ОНА БОЛЬШЕ НЕ НУЖНА

Как вы знаете, оператор C++  new  позволяет вашим программам выделять память динамически во время выполнения. Если вашей программе больше не нужна выделенная память, она должна ее освободить, используя оператор  delete.  Для освобождения памяти с использованием оператора  delete  вы просто указываете этому оператору указатель на данную область памяти, как показано ниже:

delete pointer;

Следующая программа DEL_MEM.CPP использует оператор  delete  для освобождения выделенной с помощью оператора  new  памяти:

#include <iostream.h>

#include <string.h>

void main(void)

{
   char *pointer = new char[100];
   strcpy(pointer, "Учимся программировать на языке C++");
   cout << pointer << endl;
   delete pointer; 
}

По умолчанию, если ваша программа не освобождает выделенную ей память до своего завершения, операционная система автоматически освобождает эту память после завершения программы. Однако если ваша программа использует оператор  delete  для освобождения памяти по мере того, как она (память) становится ненужной, то эта память вновь становится доступной для других целей (возможно, для вашей программы, которая опять будет использовать оператор  new,  или для операционной системы).

Второй пример

Следующая программа ALLOCARR.CPP выделяет память для хранения массива из 1000 целочисленных значений. Затем она заносит в массив значения от 1 до 1000, выводя их на экран. Потом программа освобождает эту память и распределяет память для массива из 2000 значений с плавающей точкой, занося в массив значения от 1.0 до 2000.0:

#include <iostreain.h>

void main(void)

{
   int *int_array = new int[1000];
   float *float_array;
   int i;
   if (int_array 1= NULL)

   {
      for (i = 0; i < 1000; i++) int_array[i] = i + 1;
      for (i = 0; i < 1000; i++) cout << int_array[i] << " ";
      delete int_array;
   }
   float_array = new float[2000];
   if (float_array != NULL)

   {
      for (i = 0; i < 2000; i++) float_array[i] = (i + 1) 1.0;
      for (i = 0; i < 2000; i++) cout << float_array[i] << " " ;
      delete float_array;
   }
}

Как правило, ваши программы должны освобождать память с помощью оператора  delete  по мере того, как память становится программам не нужна.

ЧТО ВАМ НЕОБХОДИМО ЗНАТЬ

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

    1. Способность выделять память динамически во время выполнения снимает с ваших программ зависимость от фиксированных размеров массивов.
    2. Если оператор  new  успешно выделяет требуемую вашей программой память, он возвращает указатель на начало области этой памяти.
    3. Если оператор  new  не может выделить требуемую вашей программой память, он возвращает NULL-указатель, который содержит значение 0.
    4. Каждый раз, когда ваши программы распределяют память динамически с использованием оператора  new,  они должны проверять значение возвращаемого оператором  new  указателя, чтобы определить, не равен ли он NULL, что указывает на невозможность выделения памяти.
    5. Используя указатель на массив, ваши программы могут обращаться к памяти, выделенной с помощью оператора  new.
    6. Оператор  new  выделяет память из блока неиспользуемой памяти, называемой свободной памятью.
    7. В зависимости от вашей операционной системы и модели памяти компилятора размер свободной памяти может быть различным. В среде MS-DOS свободная память может быть ограничена 64 Кбайт.
    8. Если вашей программе больше не нужна выделенная память, она должна освободить ее (вернуть в свободную память), используя для этого оператор  delete.

Страница сайта http://test.interface.ru
Оригинал находится по адресу http://test.interface.ru/home.asp?artId=29426