Учебники

C ++ Динамическая Память

Хорошее понимание того, как динамическая память действительно работает в C ++, необходимо для того, чтобы стать хорошим программистом C ++. Память в вашей C ++ программе делится на две части —

  • Стек — все переменные, объявленные внутри функции, будут занимать память из стека.

  • Куча — это неиспользуемая память программы и может использоваться для динамического выделения памяти при запуске программы.

Стек — все переменные, объявленные внутри функции, будут занимать память из стека.

Куча — это неиспользуемая память программы и может использоваться для динамического выделения памяти при запуске программы.

Много раз вы не знаете заранее, сколько памяти вам понадобится для хранения конкретной информации в определенной переменной, и размер требуемой памяти можно определить во время выполнения.

Вы можете выделить память во время выполнения в куче для переменной данного типа, используя специальный оператор в C ++, который возвращает адрес выделенного пространства. Этот оператор называется новым оператором.

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

новые и удаленные операторы

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

new data-type;

Здесь тип данных может быть любым встроенным типом данных, включая массив, или любые определенные пользователем типы данных, включая класс или структуру. Давайте начнем со встроенных типов данных. Например, мы можем определить указатель на тип double и затем запросить выделение памяти во время выполнения. Мы можем сделать это используя оператор new со следующими утверждениями:

double* pvalue  = NULL; // Pointer initialized with null
pvalue  = new double;   // Request memory for the variable

Память, возможно, не была распределена успешно, если свободное хранилище было использовано. Поэтому рекомендуется проверять, возвращает ли новый оператор указатель NULL, и предпринимать соответствующие действия, как показано ниже:

double* pvalue  = NULL;
if( !(pvalue  = new double )) {
   cout << "Error: out of memory." <<endl;
   exit(1);
}

Функция malloc () из C все еще существует в C ++, но рекомендуется избегать использования функции malloc (). Основное преимущество new перед malloc () состоит в том, что new не просто выделяет память, он создает объекты, которые являются основной целью C ++.

В любой момент, когда вы чувствуете, что переменная, которая была динамически распределена, больше не требуется, вы можете освободить память, которую она занимает в свободном хранилище, с помощью оператора delete следующим образом:

delete pvalue;        // Release memory pointed to by pvalue

Давайте изложим вышеизложенные понятия и сформируем следующий пример, чтобы показать, как работают «new» и «delete»:

Live Demo

#include <iostream>
using namespace std;

int main () {
   double* pvalue  = NULL; // Pointer initialized with null
   pvalue  = new double;   // Request memory for the variable
 
   *pvalue = 29494.99;     // Store value at allocated address
   cout << "Value of pvalue : " << *pvalue << endl;

   delete pvalue;         // free up the memory.

   return 0;
}

Если мы скомпилируем и запустим приведенный выше код, это даст следующий результат —

Value of pvalue : 29495

Динамическое выделение памяти для массивов

Предположим, вы хотите выделить память для массива символов, то есть строки из 20 символов. Используя тот же синтаксис, который мы использовали выше, мы можем динамически распределять память, как показано ниже.

char* pvalue  = NULL;         // Pointer initialized with null
pvalue  = new char[20];       // Request memory for the variable

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

delete [] pvalue;             // Delete array pointed to by pvalue

Следуя аналогичному универсальному синтаксису оператора new, вы можете выделить многомерный массив следующим образом:

double** pvalue  = NULL;      // Pointer initialized with null 
pvalue  = new double [3][4];  // Allocate memory for a 3x4 array 

Однако синтаксис для освобождения памяти для многомерного массива все равно останется таким же, как и выше —

delete [] pvalue;            // Delete array pointed to by pvalue

Динамическое выделение памяти для объектов

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

Live Demo

#include <iostream>
using namespace std;

class Box {
   public:
      Box() { 
         cout << "Constructor called!" <<endl; 
      }
      ~Box() { 
         cout << "Destructor called!" <<endl; 
      }
};
int main() {
   Box* myBoxArray = new Box[4];
   delete [] myBoxArray; // Delete array

   return 0;
}

Если бы вам нужно было выделить массив из четырех объектов Box, конструктор Simple был бы вызван четыре раза, и, аналогично, при удалении этих объектов деструктор также будет вызываться одинаковое количество раз.

Если мы скомпилируем и запустим приведенный выше код, это даст следующий результат —