Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Data Structures and Algorithms in C++ 2e (На ру...docx
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
2.37 Mб
Скачать

14.1. Управление памятью

интервал recursiveFactorial (интервал n)

если (n == 0) возвращаются 1;

еще возвратите n * recursiveFactorial (n-1);

//рекурсивная функция факториала / / bas i s аварий e//рекурсивный случай

669

Кодовый Фрагмент 14.1: рекурсивное внедрение функции факториала.

1 немедленно, не призывая себя рекурсивно. Стек во время выполнения допускает факториал функции, чтобы существовать одновременно в нескольких активных структурах (целый n в некоторый момент). Каждая структура хранит ценность своего параметра n, а также стоимость к

быть возвращенным. В конечном счете, когда первый рекурсивный вызов заканчивается, он возвращается (n- 1)!,

который тогда умножен на n, чтобы вычислить n! для оригинального требования факториала

функция.

14.1.1 Распределение памяти в C ++

Мы уже обсудили (в Разделе 14.1), как C ++ система во время выполнения ассигнует

местные переменные функции в структуре той функции на стеке во время выполнения. Стек не единственный вид памяти, доступной для данных о программе в C ++, как бы то ни было. Память может также быть ассигнована динамично при помощи нового оператора, который встроен в C ++. Например, в Главе 1, мы узнали, что можем ассигновать множество 100 целых чисел следующим образом:

интервал* пункты = новый интервал [100];

Память, ассигнованная этим способом, может быть освобождена с, «удаляют [] пункты».

Куча памяти

Вместо того, чтобы использовать стек во время выполнения для памяти этого объекта, C ++ использует память

из другой области хранения - куча памяти (который не должен быть перепутан со структурой данных «кучи», обсужденной в Главе 8). Мы иллюстрируем эту область памяти, вместе с другими областями памяти, в рисунке 14.2. Хранение, доступное в куче памяти, разделено на блоки, которые являются смежными подобными множеству «кусками» памяти, которая может иметь переменные или фиксированные размеры.

Чтобы упростить обсуждение, давайте предположим, что блоки в куче памяти имеют фиксированный размер, скажем, 1, 024 байта, и что один блок достаточно большой для любого объекта, который мы могли бы хотеть создать. (Эффективно обработка более общего случая является фактически интересной проблемой исследования.)

Куча памяти должна быть в состоянии ассигновать блоки памяти быстро для новых объектов. Различные системы во время выполнения используют разные подходы. Мы поэтому осуществляем эту свободу и принимаем решение использовать очередь, чтобы управлять неиспользованными блоками в куче памяти. Когда функция использует нового оператора, чтобы просить блок памяти для

670 Глава 14. Управление памятью и b-деревья

Рисунок 14.2: схематическое представление о расположении памяти в C ++ программа.

некоторый новый объект, система во время выполнения может выполнить dequeue операцию на очереди неиспользованных блоков, чтобы обеспечить свободный блок памяти в куче памяти. Аналогично, когда пользователь освобождает блок использования памяти, удаляют, тогда пробег - система времени может выполнить поставить в очередь операцию, чтобы возвратить этот блок очереди доступных блоков.

Алгоритмы распределения памяти

Важно что системы во время выполнения современных языков программирования, такого

как C ++ и Ява, в состоянии быстро ассигновать память для новых объектов. Различные системы принимают подходы различия. Один популярный метод должен держать смежные «отверстия» доступной бесплатной памяти во вдвойне связанном списке, названном бесплатным списком. Связи, присоединяющиеся к этим отверстиям, сохранены в самих отверстиях, так как их память не используется. Поскольку память ассигнована и освобождена, коллекция отверстий в бесплатных изменениях списков, с неиспользованной памятью, разделяемой на несвязные отверстия, разделенные на блоки используемой памяти. Это разделение неиспользованной памяти в отдельные отверстия известно как фрагментация. Конечно, мы хотели бы минимизировать фрагментацию как можно больше.

Есть два вида фрагментации, которая может произойти. Внутренняя фрагментация происходит, когда часть ассигнованного блока памяти фактически не используется. Например, программа может просить множество размера 1000, но только использовать первые 100 клеток этого множества. Нет очень, который окружающая среда во время выполнения может сделать, чтобы уменьшить внутреннюю фрагментацию. Внешняя фрагментация, с другой стороны, происходит, когда есть существенное количество неиспользованной памяти между несколькими смежными блоками ассигнованной памяти. Так как окружающая среда во время выполнения управляет, где ассигновать память, когда это требуют (например, когда новое ключевое слово используется в C ++), окружающая среда во время выполнения должна ассигновать память в пути, который пытается уменьшить внешнюю фрагментацию как можно больше.

Несколько эвристик были предложены для распределения памяти от кучи, чтобы минимизировать внешнюю фрагментацию. Хорошо-пригодный алгоритм ищет весь бесплатный список, чтобы найти отверстие, размер которого является самым близким на сумму памяти, которую требуют. Алгоритм первой подгонки ищет с начала бесплатного списка для первого отверстия, которое является достаточно большим. Следующий пригодный алгоритм подобен, в котором он также ищет бесплатный список первое отверстие, которое является достаточно большим, но он начинает свой поиск