Вместо того, чтобы пытаться понять auto_ptr
и его отношение к ссылкам, собираемым мусором, вы должны действительно попытаться увидеть базовый шаблон:
В C ++ все локальные объекты имеют свои деструкторы, вызываемые, когда они выходят из области видимости. Это может быть использовано для очистки памяти. Например, , мы могли бы написать класс, который в своем конструкторе получает указатель на память, выделенную из кучи, а в своем деструкторе освобождает этот указатель.
Это в значительной степени то, что делает auto_ptr
. (К сожалению, auto_ptr
также имеет несколько необычную причудливую семантику для назначения и копирования)
Это также то, что делают boost::shared_ptr
или другие умные указатели. В этом нет магии. Это просто классы, которым в своем конструкторе дан указатель, и, поскольку они обычно размещаются в стеке, они в какой-то момент автоматически выйдут из области видимости, и поэтому вызывается их деструктор, который может удалить указатель Вы изначально перешли к конструктору. Вы можете написать такие классы самостоятельно. Опять же, никакой магии, просто прямое применение правил жизни C ++: когда локальный объект выходит из области видимости, вызывается его деструктор.
Многие другие классы исключают посредников и просто позволяют одному и тому же классу выполнять как распределение, так и освобождение. Например, std::vector
вызывает new
по мере необходимости для создания своего внутреннего массива - и в своем деструкторе он вызывает delete
для его освобождения.
Когда вектор копируется, он заботится о том, чтобы выделить новый массив и скопировать содержимое из исходного, чтобы у каждого объекта был свой собственный закрытый массив.
auto_ptr
, или умные указатели в целом, не являются святым Граалем. Они не «решают» проблему управления памятью. Они являются одной из полезных частей рецепта, но чтобы избежать ошибок управления памятью и головной боли, вам необходимо понимать базовый шаблон (обычно известный как RAII ) - то есть, когда у вас есть распределение ресурсов, оно должен быть привязан к локальной переменной, которая также отвечает за ее очистку.
Иногда это означает, что вы сами вызываете new
для выделения памяти, а затем передаете результат в auto_ptr
, но чаще всего это означает, что вы сначала не вызываете new
- просто создайте нужный вам объект в стеке, и пусть он вызывает new
, как требуется внутри. Или, возможно, даже не нужно звонить new
внутри страны. Хитрость в управлении памятью заключается в том, чтобы просто полагаться на объекты, выделенные локальным стеком, а не на выделение кучи. Не используйте new
по умолчанию.