Вы можете думать о разнице между T
и Box<T>
как о разнице между статически размещенным объектом и динамически размещаемым объектом (последний создается с помощью выражения new
в терминах C ++).
В Rust и T
, и Box<T>
представляют переменную, которая имеет владение над референтным объектом (т. Е. Когда переменная выходит из области видимости, объект будет уничтожен, независимо от того, был ли онхранится по значению или по ссылке).Напротив, &T
и &mut T
представляют заимствование объекта (т.е. эти переменные не несут ответственности за уничтожение объекта и не могут пережить владельца объекта).
По умолчанию вы, вероятно, захотите использовать T
, но иногда вы можете захотеть (или иметь) использовать Box<T>
.Например, вы должны использовать Box<T>
, если хотите иметь T
, который слишком велик для размещения на месте (например, в стеке).Вы также можете использовать его, когда объект вообще не имеет известного размера, что означает, что ваш единственный способ сохранить его или передать его - через «указатель» (Box<T>
).
В Rust объект, как правило, является либо изменяемым, либо псевдонимом, но не обоими.Если вы выдавали неизменные ссылки на объект, вам обычно нужно подождать, пока эти ссылки не закончатся, прежде чем вы сможете снова изменить этот объект.
Кроме того, неизменность Rust является транзитивной.Если вы получаете объект неизменяемым образом, это означает, что у вас есть доступ к его содержимому (и содержимому этого содержимого и т. Д.) Также неизменным.
Обычно все эти элементы применяются во время компиляции.Это означает, что вы улавливаете ошибки быстрее, но вы ограничены в возможности выразить только то, что компилятор может доказать статически.
Как и T
и Box<T>
, иногда вы можете использовать RefCell<T>
, чтодругой тип собственности.Но в отличие от T
и Box<T>
, RefCell<T>
применяет правила проверки заимствования во время выполнения вместо времени компиляции, а это означает, что иногда вы можете делать с ним что-то безопасное, но не проходящееСтатическая проверка заимствования компилятора.Основным примером этого является получение изменяемой ссылки на внутреннюю часть объекта, которая была получена неизменной (что, согласно статически установленным правилам Rust, сделает всю внутреннюю часть неизменной).
Типы Ref<T>
и RefMut<T>
- это проверенные во время выполнения эквиваленты &T
и &mut T
соответственно.
Модель владения Rust пытается подтолкнуть вас к написанию программ, в которых время жизни объектов известно во время компиляции.Это работает хорошо в определенных сценариях, но делает другие сценарии трудными или невозможными для выражения.
Rc<T>
и его атомный родной элемент Arc<T>
являются обертками подсчета ссылок T
.Они предлагают вам альтернативу модели владения.
Они полезны, когда вы хотите использовать и правильно распоряжаться объектом, но это не так просто (или невозможно) определить, когда вы пишетекод, конкретная переменная которого должна быть владельцем этого объекта (и, следовательно, должна позаботиться о его удалении).Как и в C ++, это означает, что нет единого владельца объекта и что объект будет удален последней обёрткой подсчета ссылок, которая на него указывает.