用于处理借用数据的模块: std::borrow
1 Borrow
#![allow(unused)] fn main() { pub trait Borrow<Borrowed> where Borrowed: ?Sized, { // Required method fn borrow(&self) -> &Borrowed; } }
一个用于借用数据的trait.
通过实现Borrow<T>来表达它们可以作为其个类型T借出.并在trait的borrow方法中提供对T的引用.
例如: String实现了Borrow<str>,则可以作为str进行借出, Box<T>实现了Borrow<T>,则可以作为T进行借出
2. BorrowMut
#![allow(unused)] fn main() { pub trait BorrowMut<Borrowed>: Borrow<Borrowed> where Borrowed: ?Sized, { // Required method fn borrow_mut(&mut self) -> &mut Borrowed; } }
一个用于可变借用数据的trait.
作为Borrow<T>的补充,该trait允许类型通过提供可变引用来借用底层类型.
3. ToOwned
#![allow(unused)] fn main() { pub trait ToOwned { type Owned: Borrow<Self>; // Required method fn to_owned(&self) -> Self::Owned; // Provided method fn clone_into(&self, target: &mut Self::Owned) { ... } } }
Clone在借用数据上的泛化.
Clone一般是&T到T, ToOwned trait 将Clone泛化, 可以从给定类型的任何借用中构造拥有数据.
这里关联类型Owned需要满足Borrow<Self> trait, 此处Self为要实现ToOwned的结构.
看下 str对ToOwned trait 的实现:
#![allow(unused)] fn main() { impl ToOwned for str { type Owned = String // Required method fn to_owned(&self) -> Self::Owned { ... } // Provided method fn clone_into(&self, target: &mut Self::Owned) { ... } } }
关联类型Owned被定义为String, 而根据要求,String必须定义Borrow<T>,那这里Borrow里的泛型变量T是谁呢?
ToOwned要求是Borrow<Self>,而此刻实现 ToOwned 的主体是 str,所以 Borrow<Self> 是 Borrow<str>, 而String的确实现了Borrow<str>.
4. Cow
#![allow(unused)] fn main() { pub enum Cow<'a, B> where B: 'a + ToOwned + ?Sized, { Borrowed(&'a B), Owned(<B as ToOwned>::Owned), } }
Cow用于提供写时克隆(Clone-on-Write)的一个智能指针,包裹一个只读借用,但如果调用者需要所有权或者需要修改内容,那么它会 clone 借用的数据.
Cow实现了Deref trait.
#![allow(unused)] fn main() { impl<B: ?Sized + ToOwned> Deref for Cow<'_, B> { type Target = B; fn deref(&self) -> &B { match *self { Borrowed(borrowed) => borrowed, Owned(ref owned) => owned.borrow(), } } } }