原生的引用和可变引用类型我们再熟悉不过了,Rust 代码根本离不开它。但是你真的了解这位老熟人吗?
或许阅读下面的内容,你会有新的理解和收获。
引用(Reference)表示对某个拥有所有权的值的借用(borrow)。我们通过对值使用 & 或 &mut 运算符,或者使用 ref、ref mut 来获取引用。
引用实质上就是一个指针,但它被假定为已对齐的(aligned)、非空的(not null),并且指向包含有效值的内存(pointing to memory containing a valid value)。违反所述任何一条都会导致未定义行为(undefined behavior)。比如 &bool 只能指向包含整数值 1(true)或 0(false)的内存分配,而不能指向包含值 3 的内存分配。
无论被引用者的类型是什么,所有 &T 都实现了以下特征:
Copy 和 Clone(注意:即使 T 存在 Clone 的实现,此处的 Clone 也不会委托给 T 的实现)DerefBorrowfmt::Pointer无论被引用者的类型是什么,&mut T 引用都自动实现了上述除 Copy 和 Clone(这是为了防止同时创建多个可变借用)以外所有的特征实现,此外还增加了以下特征:
DerefMutBorrowMut可以看到,两种引用类型都实现了 Deref,因此它们都算作智能指针。
如果底层类型 T 实现了以下特定的特征,那么 &T 引用也会相应地实现:
std::fmt 中的所有特征,fmt::Write 除外。其中 fmt::Pointer 无论被引用类型是什么它都会实现PartialOrd 与 OrdPartialEq 与 EqAsRefFn(另外如果 T: Fn,则 &T 引用也会获得 FnMut 和 FnOnce 实现)HashToSocketAddrsSync如果底层类型 T 实现了相关特征,&mut T 引用都自动实现了上述除 ToSocketAddrs 以外所有的特征实现,外加以下特征:
AsMutFnMut(另外如果 T: FnMut,则 &mut T 引用也会获得 FnOnce 实现)fmt::WriteIterator、DoubleEndedIterator、ExactSizeIterator 与 FusedIteratorTrustedLenSendio::Write、Read、Seek 与 BufRead