- •Конспект лекций Часть 2 Оглавление
- •Часть 2 1
- •8. Указатели
- •8.1. Указатели Понятие указателя
- •Работа с указателями
- •Арифметика указателей
- •Ошибки при работе с указателями
- •If (p1) // Если указатель не равен 0, то все в порядке
- •8.2. Указатели и массивы
- •9. Функции и структура программы
- •9.1. Создание и использование функций Процедурный подход к разработке программ
- •Определение функций в программе
- •Завершение работы функции (инструкция return)
- •If ( Ошибка )
- •Список параметров функций
- •Обращение к функциям в программе
- •Передача данных по значению
- •Передача данных с помощью указателей
- •Передача данных по ссылке
- •Перегружаемые функции
- •Параметры по умолчанию
- •Функции с переменным числом параметров
- •Рекурсивное использование функций
- •Передача функций в качестве параметров
- •Встраиваемые функции (inline - функции)
- •Прототипы функций
- •9.2. Структура программы. Глобальные и локальные данные (области видимости и время жизни) Структура программы
- •Глобальные и локальные данные
- •Классы памяти
- •Доступ к полям структур
- •Указатели на структуры
- •Структурные параметры функций
- •Битовые поля структур
- •10.2. Объединения Обычные объединения
- •Анонимные объединения
- •10.3. Перечисления
- •Void WriteColor (тип_Спектр c )
- •11. Организация ввода/вывода и работа с файлами
- •11.1. Потоки для работы с файлами Общие сведения
- •Пример работы с файлом
- •Создание потока, открытие и закрытие файла
- •Запись и чтение данных в текстовых файлах
- •Запись и чтение данных в двоичном режиме
- •If ( !File ) // Проверили удалось ли открыть файл
- •Как обнаружить конец файла?
- •Прямой доступ при работе с файлами
- •If ( !File ) // Проверили удалось ли открыть файл
- •Статус потоков ввода-вывода
- •Некоторые другие функции управления потоками ввода-вывода
- •Примеры по работе с файлами
- •12. Работа с динамической памятью Распределение памяти при работе программы
- •Динамическое выделение и освобождение памяти в стиле c
- •Возможные ошибки при работе с динамической памятью
- •Динамические массивы
- •Продолжение следует …
Динамическое выделение и освобождение памяти в стиле c
Язык C++ поддерживает и “старый”, заимствованный от языка C, стиль работы с динамической областью. Достаточно часто бывает полезно использовать именно этот механизм управления динамической памятью, так как он предоставляет несколько более широкий спектр “услуг”.
В языке C отсутствуют инструкции new и delete. Вместо них для управления динамической памятью используются библиотечные функции, имеющие следующие прототипы:
void *malloc ( size_t size );
void *calloc( size_t num, size_t size );
void free( void *memblock );
void *realloc( void *memblock, size_t size );
Функция malloc выделяет в динамической области size байт памяти (тип данных size_t представляет собой разновидность беззнакового целого типа данных) и возвращает адрес этого участка в виде нетипизированного указателя (void *). Поскольку возвращаемый указатель не привязан ни к какому типу данных, при работе с ним потребуется явное приведение типов данных (см. пример ниже).
Функция calloc выделяет в динамической области size * num байт памяти и возвращает адрес этого участка в виде не типизированного указателя (void *).
Функция free освобождает участок динамической памяти по адресу memblock и возвращает его в список свободной памяти для повторного использования.
Функция realloc позволяет изменить размер (уменьшить или увеличить) ранее выделенной по адресу memblock памяти, установив новый размер выделенного участка равным size байт. При увеличении размера выделенного участка данные, которые хранились в старом участке, копируются в новый участок памяти. При уменьшении объема выделенного участка, данные которые хранились в нем, усекаются до нового размера. Функция возвращает нетипизированный указатель на область памяти нового размера.
Предыдущий пример, переделанный под стиль C, выглядит так:
struct t_Person // Тип данных для "персоны"
{
char Fam[20]; // Фамилия
char Name[20]; // Имя
int Year; // Год рождения
};
setlocale ( 0, "" ); // Русификация консоли
t_Person *p; // Определяем указатель на тип t_Person
p = ( t_Person * ) malloc ( sizeof ( t_Person ) ); // Выделяем память и используем
// приведение нетипизированного указателя к указателю на тип данных t_Person
strcpy ( p -> Fam, "Иванов" ); // Заносим фамилию
strcpy ( p -> Name, "Иван" ); // Заносим имя
p -> Year = 1995; // Заносим год рождения
cout << "Фамилия: " << p -> Fam << endl; // Выводим фамилию
cout << "Имя: " << p -> Name << endl; // Выводим имя
cout << "Год рождения: " << p -> Year << endl; // Выводим год рождения
free ( p ); // Освобождаем память
Для переделки программы под стиль C потребовались всего два изменения в программе (эти места выделены красным цветом).
В одной и той же программе не рекомендуется смешивать использование “старого” и “нового” стилей работы с динамической памятью (возможны проблемы с совместимостью).
Другие возможности (некоторые преимущества) этого стиля работы с динамической памятью будут рассмотрены далее при изучении динамических массивов.