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. Ссылки обозначаются символом & и заимствуют значение, на которое указывают. У них нет никаких особых возможностей, кроме ссылки на данные, и они не имеют накладных расходов.

Умные указатели, с другой стороны, — это структуры данных, которые действуют как указатель, но также имеют дополнительную метаданные и возможности. Концепция умных указателей не уникальна для Rust: умные указатели появились в C++ и существуют в других языках. В Rust есть множество умных указателей, определённых в стандартной библиотеке, которые предоставляют функциональность, выходящую за рамки возможностей ссылок. Чтобы изучить общую концепцию, мы рассмотрим несколько различных примеров умных указателей, включая типаж управления счётчиком ссылок. Этот указатель позволяет данным иметь нескольких владельцев, отслеживая количество владельцев и очищая данные, когда владельцев не остаётся.

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

Хотя мы не называли их таковыми в то время, мы уже встречали несколько умных указателей в этой книге, включая String и Vec<T> в Главе 8. Оба этих типа считаются умными указателями, потому что они владеют некоторой памятью и позволяют вам управлять ею. Они также имеют метаданные и дополнительные возможности или гарантии. String, например, хранит свою ёмкость как метаданные и имеет дополнительную возможность гарантировать, что его данные всегда будут действительными UTF-8.

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

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

  • Box<T>, для размещения значений в куче
  • Rc<T>, типаж управления счётчиком ссылок, который позволяет множественное владение
  • Ref<T> и RefMut<T>, доступные через RefCell<T>, тип, который обеспечивает соблюдение правил заимствования во время выполнения, а не на этапе компиляции

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

Давайте начнём!