
- •1. Введение
- •2. Элементы языка
- •2.1. Первые программы
- •2.2. Алфавит языка
- •2.3. Комментарии
- •2.4. Типы данных
- •2.5. Целые типы данных
- •2.6. Плавающие типы данных
- •2.7. Константы-строки, или литералы
- •2.8. Директива препроцессора define
- •2.9. Описания
- •2.10. Модификатор const
- •3. Выражения
- •3.1. Операция и выражение присваивания
- •3.2. Арифметические операции
- •3.3. Операции отношения
- •3.4. Логические операции
- •3.5. Побитовые операции
- •3.6. Сдвиги
- •?????3.8. Тернарная или условная операция
- •3.9. Операция следования
- •3.10. Приоритеты операций и порядок вычисления
- •4.6. Оператор выбора switch
- •4.7. Оператор цикла while
- •4.8. Цикл с постусловием do-while
- •4.9. Оператор for
- •4.10. Оператор безусловного перехода
- •4.11. Оператор break
- •4.12. Оператор continue
- •4.13. Оператор return
- •5. Указатели
- •5.1. Определение указателей
- •5.2. Указатели и массивы
- •5.3. Адресная арифметика
- •5.4. Символьные массивы и строки
- •5.5. Многомерные массивы
- •5.6. Указатели и многомерные массивы
- •6. Операция sizeof
- •7. Операции для работы с динамической памятью
- •7.1. Операция выделения памяти new
- •7.2. Операция освобождения памяти delete
- •8. Функции
- •8.1. Определение и вызов функции
- •8.2. Функции. Передача аргументов
- •8.3. Передача многомерных массивов
- •8.4. Указатели на функции
- •8.5. Ссылки
- •8.6. Ссылки в качестве параметров функций
- •8.7. Аргументы по умолчанию
- •8.8. Переопределение функций
- •8.9. Шаблоны функций
- •9. Объявления и определения
- •10. Область существования имени
- •11. Область видимости
- •Здесь будет напечатано
- •12. Классы памяти
- •13. Объявления объектов и типов
- •14. Имена типов
- •15. Синоним имени типа
- •16. Правила преобразования стандартных типов
- •16.1. Явные преобразования
- •16.2. Неявные преобразования стандартных базовых типов
- •16.3. Преобразование производных стандартных типов
- •17. Перечисления
- •18. Классы
- •18.1. Объявление классов
- •18.2. Конструкторы
- •18.3. Деструкторы
- •18.4. Статические члены класса
- •18.5. Указатель this
- •18.6. Статические функции-члены
- •18.7. Указатели на члены класса
- •18.8. Инициализация данных–членов класса
- •18.9. Конструктор копирования и операция присваивания
- •18.10. Дружественные функции
- •18.11. Конструктор и операция new
- •18.12. Вызов деструктора
- •19. Производные классы
- •19.1. Построение производного класса
- •19.2. Защищенные члены класса
- •19.3. Управление уровнем доступа к членам класса
- •19.4. Последовательность вызова конструктора и деструктора при построении производного класса на основе одного базового
- •19.5. Преобразования типов
- •20. Полиморфизм
- •20.1. Раннее и позднее связывание
- •20.2. Виртуальные функции
- •20.3. Абстрактные классы
- •21. Переопределение стандартных операций
- •21.1. Основные определения и свойства
- •21.2. Операции new и delete при работе с абстрактными типами
- •21.3. Использование new при создании динамического объекта абстрактного типа
- •21.4. Операция delete
- •21.5. Преобразование типов
- •22. Некоторые особенности переопределенных операций
- •22.2. Операция [ ]
- •23. Классы и шаблоны
- •24. Списки
- •24.1. Операции над односвязными списками
- •24.2. Двунаправленные и кольцевые списки
- •24.3. Операции над кольцевыми списками
- •25. Стеки
- •25.1. Реализация стека через массив
- •25.2. Реализация стека через динамическую цепочку звеньев
- •26. Двоичные деревья
- •26.1. Определение и построение
- •26.2.Таблицы
- •27. Список литературы
7. Операции для работы с динамической памятью
7.1. Операция выделения памяти new
Часто выражение, содержащее операцию new, имеет следующий вид:
указатель_на_тип_= new имя_типа (инициализатор)
Инициализатор - это необязательное инициализирующее выражение, которое может использоваться для всех типов, кроме массивов.
При выполнении оператора
int *ip = new int;
создаются 2 объекта: динамический безымянный объект и указатель на него с именем ip, значением которого является адрес динамического объекта. Можно создать и другой указатель на тот же динамический объект:
int *other=ip;
-
ip
int
-
other
Если указателю ip присвоить другое значение, то можно потерять доступ к динамическому объекту:
int *ip=new (int);
int i=0;
ip=&i;
-
ip
int
-
i
В результате динамический объект по-прежнему будет существовать, но обратится к нему уже нельзя. Такие объекты называются мусором.
При выделении памяти объект можно инициализировать:
int *ip = new int(3);
Можно динамически распределить память и под массив:
double *mas = new double [50];
-
mas
. . . . .
Теперь с этой динамически выделенной памятью можно работать как с обычным массивом:
*(mas+5) = 3.27;
mas[6] = mas[5] + sin(mas[5]);
В случае успешного завершения операция new возвращает указатель со значением, отличным от нуля.
Результат операции, равный 0, т.е. нулевому указателю NULL, говорит о том, что не найден непрерывный свободный фрагмент памяти нужного размера.
7.2. Операция освобождения памяти delete
Операция delete освобождает для дальнейшего использования в программе участок памяти, ранее выделенной операцией new:
delete ip; // Удаляет динамический объект типа int,
// если было ip = new int;
delete mas; // удаляет динамический массив длиной 50, если было
// double *mas = new double[50];
Совершенно безопасно применять операцию к указателю NULL. Результат же повторного применения операции delete к одному и тому же указателю не определен. Обычно происходит ошибка, приводящая к зацикливанию.
Чтобы избежать подобных ошибок, можно применять следующую конструкцию:
int *ip=new int[500];
. . .
if (ip){delete ip; ip=NULL;}
else { cout <<“ память уже освобождена \n”; }
Пример:
Распределить память для матрицы из m строк и n столбцов:
int m, n;
cout<<”Задайте число строк и столбцов матрицы: \n”;
cin>>m>>n;
double **a = new double *[m]; // массив из n указателей на double
for (int i = 0; i<m; i++ )
if ((a[ i ] = new double[n])==NULL) // Распределяется строка матрицы
{ cout<<”Нет памяти!\n”; exit(1);}
Теперь к элементам этой матрицы можно обращаться обычным образом:
a[ i ][ j ] или *(a[ i ]+j) или *(*(a+i)+j)
Изобразить распределение памяти, соответствующее вышеприведенному фрагменту можно следующим образом:
Освободить память здесь можно так:
for (i=0; i<m; i++)delete a[ i ];
delete a;
Или так:
for(i=0; i<m; i++) {delete a[ i ]; a[ i ]=NULL;}
delete a;