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

Язык C++ / Динамическое выделение памяти

В С работать с динамической памятью можно при помощи соответствующих функций распределения памяти (calloc, malloc, free), для чего необходимо подключить библиотеку

#include <malloc.h>

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

  • new — для выделения памяти;
  • delete — для освобождения памяти.

Оператор new используется в следующих формах:

new тип;  // для переменных
new тип[размер];  // для массивов

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

int *ptr_i;
double *ptr_d;
struct person *human;
...
ptr_i = new int;
ptr_d = new double[10];
human = new struct person;

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

Освобождение памяти связано с тем, как выделялась память – для одного элемента или для нескольких. В соответствии с этим существует и две формы применения delete:

delete указатель;  // для одного элемента
delete[] указатель;  // для массива

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

delete ptr_i;
delete[] ptr_d;
delete human;

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

#include <iostream>
using namespace std;
int main() {
  int size;
  int *dan;
  system("chcp 1251");
  system("cls");
  cout << "Ввести размерность массива: ";
  cin >> size;
  dan = new int[size];
  for (int i=0; i<size; i++) {
    cout << "dan[" << i << "]= ";
    cin >> dan[i];
  }
  for (int i=0; i<size; i++)
    cout << dan[i] << " ";
  delete[] dan;
  cin.get(); cin.get();
  return 0;
}

Результат выполнения
Операторы new и delete

Указатель dan – базовый адрес динамически распределяемого массива, число элементов которого равно size. Операцией delete освобождается память, распределенная при помощи new.
Назад

Комментариев к записи: 10

  • я написал программу как мне устанавливать на другие компьютеры и как выложить в интернет


    • Елена Вставская

      Проще всего выложить вконтакте или на github.com.
      Но можно создать свой сайт и заниматься его оформлением и наполнением.
      А вообще пока у меня до обучения размещению информации в Интернете дело не дошло 🙂


  • А реально ли создать или написать чтобы выложить в интернет чтобы все скачивали и пользовались что я создам на языке c++?


  • Увы нет Елена. Ранее я уже писал на форуме в теме http://prog-cpp.ru/c-alloc/. Решил использовать этот же алгоритм:

    /*

    This prog introduces an advanced input in dynamic array.

    The array is pretty clever. Its reallocates itself memory

    as same as its need. The another pretty thing: very

    comfortable input.

     

    Dont be disapeared if you′ll see, the same output on screen.

    Prog created in used only for concept idea, how its good

    can to be to use this input.

    To example: input a row of numbers 1 2 3 4 5

    then press Enter, to continue input 5 4 3 2 1

    press Enter again. For another way — break —

    press ESC. Pressing ESC again will terminate the

    prog, but pressing any key will free array and let

    to continue input the new array.

    Be careful, amount of numbers in string must

    equial with another string. Else prog will

    terminate with the error code.

    */

    #include <iostream>

    #include <conio.h>

     

    #define ESC 27

    #define EOS ′\n′

     

    using namespace std;

     

    int main() {

    do {

    system("CLS");

    //creating the dynamic array[0][0] with only one free space

    float **a = (float**)malloc(sizeof(float*));

    a[0] = (float*)malloc(sizeof(float));

    int volume = 0, i = 0;//volume contains used space(bytes) in array, ′i′ need for counting below

    do {

    cout << "Enter " << i + 1 << " string: ";

    do {

    cin >> a[i][_msize(a[i]) / sizeof(float) — 1];//the ′j′ is memory of *p divided by 4, for first one 4/4 = 1, next 8/4 and etc

    if (cin.rdbuf()->in_avail() != 1) a[i] = (float*)realloc(a[i], _msize(a[i]) + sizeof(float));//realocates memory only if buffer contains more then 1 number in stack

    } while (cin.get() != EOS);//while not in the end of buffer >′cin′

     

    volume += _msize(a[i]);//increases volume 4/8/16 and etc

     

    a = (float**)realloc(a, _msize(a) * sizeof(float*));//reallocates new pointer

    a[i+1] = (float*)malloc(sizeof(float));//allocates memory for new p[]

    i++;

    } while (_getch() != ESC);//while you dont press ESC

    cout << endl << "Result achived:" << endl << endl;

    volume /= _msize(a[0]);//strings in array calc

    //output on screen

    for (int i = 0; i < volume; i++) {

    for (int j = _msize(a[i]) / sizeof(float); j > 0; j—) {//′j′ is a amount of numbers in string, 1 1 1 1 all size is 16, divided by 4 = 4

    cout << a[i][_msize(a[i]) / sizeof(float) — j] << " ";

    }

    cout << endl;

    free(a[i]);//frees memory in *p

    }

    free(a);//frees memory in **p

     

    } while (_getch() != ESC);//while you dont press ESC

    return 0;

    }

    Вот тут в прототипе все работает корректно. Однако при попытке создании структуры что-то пошло не так.


    • Елена Вставская

      А где в Вашей реализации строки

      float **a = (float**)malloc(sizeof(float*));
      a[0] = (float*)malloc(sizeof(float));

      ???
      Это и есть изначальное выделение памяти — то, о чем я говорила.


      • То есть, вы хотите сказать что:

        typedef struct {    
        float **matrix;
        }matrix;
        A.matrix = (float**)malloc(sizeof(float));
        A.matrix[0] = (float*)malloc(sizeof(float));

        Не эквивалентно:

        float **a = (float**)malloc(sizeof(float*));
        a[0] = (float*)malloc(sizeof(float));

        • Елена Вставская

          Борис,
          1) В функции input_matrix(matrix m) Вы работаете с копией матрицы, а не с ее оригиналом, поэтому после возврата из функции введенные данные недоступны. Один из способов решения этой проблемы:

          matrix input_matrix(matrix m) {

          return m;
          }

          2) Я не поняла назначение цикла dowhile в main(), но у меня он работать отказывается.
          3) Очистка памяти в конце функции производится неверно. Один из вариантов очистки памяти

          int h = A.volume / _msize(A.matrix[0]);
          // это вычисление обязательно сделать до цикла, поскольку количество строк в цикле будет меняться
          for(int i=0; i<h; i++)
          free(A.matrix[i]);
          free(A.matrix);


  • Доброго времени суток!

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

    Привожу пример кода:

    #include <iostream>
    #include <conio.h>
    #define ESC 27
    #define′\n′
    using namespace std;
     
    typedef struct {
        float **matrix;
        unsigned int volume;
        char name;
    }matrix;
     
    //функция ввода.
    void input_matrix(matrix m) {
        //если значения вводились ранее, удалить текущую матрицу
        if (m.volume != 0) {
            m.volume /= _msize(m.matrix[0]);
            for (int i = 0; i < m.volume; i++) {
                free(m.matrix[i]);
            }
            free(m.matrix);
            m.volume = 0;
        }
     
        int i = 0;
     
        do {
            cout << "Enter " << i + 1 << " string of matrix " << m.name << ": ";
            do {
                cin >> m.matrix[i][_msize(m.matrix[i]) / sizeof(float) — 1];  //текущий размер массива / размер типа = кол-во элементов в массиве. -1 это свободная ячейка
                if (cin.rdbuf()->in_avail() != 1) m.matrix[i] =
                    (float*)realloc(m.matrix[i], _msize(m.matrix[i]) + sizeof(float));  // если в очереди буфера больше 1 символа, записать и увеличить массив m[]
            } while (cin.get() != EOS);   //считать все из буфера cin, то есть до ‘\n’
            m.volume += _msize(m.matrix[i]);                      //суммирую кол-во затрачиваемой памяти
            m.matrix = (float**)realloc(m.matrix, _msize(m.matrix) * sizeof(float*));   //увеличить массив m
            m.matrix[i + 1] = (float*)malloc(sizeof(float));       //выделить память под новые элементы m[]
            i++;
        } while (_getch() != ESC);  //пока не нажал ESC повторять, увеличивая строки массива
    }
    //функция вывода на консоль
    void out_matrix(matrix m) {
        cout << "Matrix " << m.name << ":" << endl;  //вывод имени матрицы
        for (int i = 0; i < m.volume / _msize(m.matrix[0]); i++) {                  // подсчет строк путем деления общего объема на длину строки
            for (int j = _msize(m.matrix[i]) / sizeof(float); j > 0; j—) {         //подсчет элементов путем деления длины строки на тип памяти(float = 4)
                cout << m.matrix[i][_msize(m.matrix[i]) / sizeof(float) — j] << " "; //вывод элементов
            }
            cout << endl;
        }
        cout << endl;
    }
     
    int main() {
        //для примера я создам объект структуры с названием А
        matrix A;
        A.matrix = (float**)malloc(sizeof(float));
        A.matrix[0] = (float*)malloc(sizeof(float)); //выделяю 4 байта, 1 ячейка
        A.name = ′A′;   //имя задам константно
        A.volume = 0;   //начальный объем
     
        do {
            input_matrix(A);
            out_matrix(A);
            cout << "Volume: " << A.volume << endl;
        } while ( _getch() != ESC);
     
      for (int i = 0; i < A.volume; i++)      
    free(A.matrix[i]);
      free(A.matrix);
    return 0;
    }

    • Елена Вставская

      Я, конечно, не уверена на 100%, но по-моему ошибка состоит в том, что когда Вы вводите элементы первой строки матрицы, указатель на эту строку еще не определен — операция

      m.matrix = (float**)realloc(m.matrix, _msize(m.matrix) * sizeof(float*)); //увеличить массив m

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


Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *