Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Умные указатели

Указатель — общее название переменной, которая хранит адрес в памяти. Этот адрес ссылается, или «указывает», на какие-то другие данные. Самый распространённый вид указателя в Rust — ссылка, с которой вы познакомились в главе 4. Ссылки обозначаются символом & и заимствуют значение, на которое указывают. Никаких особых возможностей, кроме обращения к данным, у них нет, зато нет и накладных расходов.

Умные указатели (smart pointers) — это структуры данных, которые ведут себя как указатель, но вдобавок хранят метаданные и обладают дополнительными возможностями. Умные указатели придуманы не в Rust: они появились в C++ и есть в других языках. В стандартной библиотеке Rust определено несколько умных указателей, которые умеют больше, чем ссылки. Чтобы разобраться в общей идее, рассмотрим несколько примеров умных указателей, в том числе тип с подсчётом ссылок (reference counting). Такой указатель позволяет данным иметь нескольких владельцев: он следит за количеством владельцев и, когда их не остаётся, освобождает данные.

Поскольку в Rust есть владение и заимствование, между ссылками и умными указателями есть ещё одно различие: ссылки только заимствуют данные, а умные указатели во многих случаях владеют данными, на которые указывают.

Умные указатели обычно реализуют в виде структур. Но, в отличие от обычной структуры, умные указатели реализуют трейты Deref и Drop. Трейт Deref позволяет экземпляру умного указателя вести себя как ссылка, так что код можно писать так, чтобы он работал и со ссылками, и с умными указателями. Трейт Drop позволяет задать код, который выполняется, когда экземпляр умного указателя выходит из области видимости. В этой главе мы разберём оба трейта и покажем, почему они так важны для умных указателей.

Умный указатель — общий шаблон проектирования, который часто встречается в Rust, поэтому мы не будем разбирать все существующие умные указатели. У многих библиотек есть собственные, и вы даже можете написать свой. Мы рассмотрим самые распространённые умные указатели стандартной библиотеки:

  • Box<T> — для размещения значений в куче;
  • Rc<T> — тип с подсчётом ссылок, позволяющий иметь нескольких владельцев;
  • RefCell<T> — тип, который проверяет правила заимствования не при компиляции, а во время выполнения; доступ к значению внутри него дают Ref<T> и RefMut<T>.

Кроме того, мы разберём шаблон внутренней изменяемости (interior mutability), когда неизменяемый тип предоставляет API для изменения внутреннего значения. А ещё обсудим циклы ссылок: как они приводят к утечкам памяти и как их избежать.

Начнём!