В Си работать с динамической памятью можно при помощи соответствующих функций распределения памяти (calloc, malloc, free), для чего необходимо подключить библиотеку
malloc.h
С++ использует новые методы работы с динамической памятью при помощи операторов new и delete:
- new — для выделения памяти;
- delete — для освобождения памяти.
Оператор new используется в следующих формах:
- new тип; — для переменных
- new тип[размер]; — для массивов
Память может быть распределена для одного объекта или для массива любого типа, в том числе типа, определенного пользователем. Результатом выполнения операции new будет указатель на отведенную память, или исключение std::bad_alloc в случае ошибки.
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_d;
delete human;
Освобождаться с помощью delete может только память, выделенная оператором new.
Пример Создание динамического массива
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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;
}
Результат выполнения
Указатель dan – базовый адрес динамически распределяемого массива, число элементов которого равно size. Операцией delete освобождается память, распределенная при помощи new.
Пример неудачного выделения памяти (в случае очень большого требуемого объема):
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
using namespace std;
int main()
{
int *p = 0;
try
{
p = new int[1000000000];
}
catch(const bad_alloc& e)
{
cout << "Error: " << e.what() << '\n';
}
cout << p << endl;
return 0;
}
Назад: Язык C++
2
3
4
if (!variable) { //если не сможет выделить, вернет NULL
std::cout << "Could not allocate memory for variable"
}
А если это вспомогательный массив был, который после выхода из функции больше не нужен, то память нужно очистить в функции.
2
3
4
5
for (uint32_t i=0; i<(1000000-1); i++)
{
g *= 1.000001;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include <cstring>
char *resize(const char *str, unsigned size, unsigned new_size);
char *getline();
using namespace std;
int main()
{
char *s;
s= getline();
cout<<s<<endl;
}
// Принимает строку, размер этой строки, новый размер строки, возвращает указатель на новую строку.
char *resize(const char *str, unsigned size, unsigned new_size)
{
char *ns = new char [sizeof(char)*new_size];
for (unsigned i=0;i<new_size&&i<size;i++)
{
ns[i]=str[i];
}
delete []str;
return ns;
}
// Получаем строку и увеличиваем ее понеобходимости.
char *getline() //
{
unsigned j=1; //размер массива
char *temp= new char [j]{'\0'};
char c;
while(std::cin.get(c) && c != '\n' && c != std::cin.eof())
{
temp[j-1]=c;
temp=resize (temp,j,++j);
}
temp[j-1]='\0';
return temp;
}
В параллельном курсе stepic необходимо создать рекурсию которая будет способна возвести 1.000001 в степень 1000000 Но при такой глубине у меня рекурсия не работает. Происходит переполнение стека.
Как же работать с памятью то?
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <iostream>
using namespace std;
double m(double a, unsigned int n);
double mm(double a, double n);
int main()
{
double a=1.000001;
unsigned int b=10000; // максимально возможная степень:86674
if (b%2==0)cout<< mm (a,b);
if (b%2!=0)cout<< m(a,b);
}
double m(double a, unsigned int n)
{
if (n==0)return 1;
return a*m(a,n-1);
}
double mm(double a, double n)
{
if (n==0)return 1;
return (m(m(a,2),(n/2)));
}
///////////////////////////////////////////////////////////////////
temp=resize (temp,j,++j); - здесь ошибка.
j - в данном случае будет сначала инкрементироваться, а затем отправляться. в итоге будет нечно вроде такого j = 1
resize (temp,j,++j) - вид вызова будет такой resize (temp,2,2)
для решения необходимо вызывать так
resize (temp,j - 1,++j)
или так
resize (temp,j,j++ + 1)
или в две строки
resize (temp,j,j + 1)
j++
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
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;
}
2
a[0] = (float*)malloc(sizeof(float));
2
3
4
5
float **matrix;
}matrix;
A.matrix = (float**)malloc(sizeof(float));
A.matrix[0] = (float*)malloc(sizeof(float));
2
a[0] = (float*)malloc(sizeof(float));
2
3
4
…
return m;
}
2
3
4
5
// это вычисление обязательно сделать до цикла, поскольку количество строк в цикле будет меняться
for(int i=0; i<h; i++)
free(A.matrix[i]);
free(A.matrix);
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#include <conio.h>
#define ESC 27
#define EOS '\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;
}