216
внутренние из кучи. Как будет показано в последних главах, это играет важную роль в схемах
уплотнения и сборки мусора.
В двух следующих главах эта методика будет применяться довольно часто. Перемещаемые объекты
отделяются от объектов, остающихся на одном месте.
Ведущие указатели, доступные из стека,
находятся в одном пространстве памяти, а доступные из других процессов — в другом.
Пространства стека и кучи
Наконец, сам стек тоже можно считать разновидностью пространства памяти, а выделяемые в стеке
пулы — их частным случаем. Этот подход применялся ранее в этой главе для пулов,
локальных по
отношению к области действия конкретной функции. Эта особая интерпретация стека упоминается и в
двух последующих главах.
Уплотнение
памяти
Представьте себе обычное управление памятью в С++: вы зажигаете благовония, приносите жертву
божествам операционной системы и удаляете объект. Если все идет нормально, объект будет должным
образом деинициализирован и уничтожен и никто никогда не попытается им воспользоваться. Ха!
Всем известно, что в реальной жизни так не бывает.
Одна из главных достопримечательностей динамических языков — таких как SmallTalk и Lisp — не
имеет никакого отношения к самому языку, а лишь к тому,
что он удаляет объекты за вас,
автоматически и надежно. Выходит потрясающая экономия времени и энергии, не говоря уже о
благовониях и жертвах. Можно ли то же самое сделать на С++? Вместо прямолинейного «да» или
«нет» я отвечу: «Все зависит от того, сколько труда вы хотите вложить в решение».
В этой главе начинается настоящее веселье — вы увидите, как перемещать объекты в памяти, чтобы
свести к минимуму фрагментацию свободной памяти. Надеюсь, при виде моих алгоритмов никто не
будет кататься по полу от смеха. Заодно мы подготовим сцену для полноценных алгоритмов сборки
мусора, о которых речь пойдет в следующей главе.
Поиск указателей
Помимо подсчета ссылок и
нестандартных операторов
new
и
delete
в большинстве стратегий
управления памятью сочетаются две методики: определение момента, когда доступ к объекту
становится невозможным, для его автоматического уничтожения (сборка мусора) и
перемещение
объектов в памяти (уплотнение). В свою очередь, эти стратегии зависят от того, что в других языках
делается легко и просто, но оказывается дьявольски сложным в С++ — от задачи поиска всех
указателей на объекты.
Поиск указателей в программе на С++ чрезвычайно сложен, поскольку компилятор не оставляет
никаких инструкций на этот счет. Более того, в С++ программа может получить адрес части объекта,
поэтому некоторые указатели могут ссылаться на середину большого объекта.
Мама, откуда берутся указатели?
В С++ существуют невероятно разнообразные способы получения указателей.
Одни связаны с
конкретным представлением объектов в памяти, другие — с наследованием, третьи — с переменными
классов. Конечно, самый очевидный способ — это нахождение адреса. А теперь давайте рассмотрим
другие, не столь тривиальные способы.
Адреса переменных класса
Имея объект, вы можете получить адрес переменной класса, поспользоваться им или передать другому
объекту.
class Foo {
private:
int
x;
String
y;
Do'stlaringiz bilan baham: