集合是智能指针
描述
使用Dereftrait将集合视为智能指针,提供拥有
和借用的数据视图。
例子
use std::ops::Deref;
struct Vec<T> {
data: RawVec<T>,
//..
}
impl<T> Deref for Vec<T> {
type Target = [T];
fn deref(&self) -> &[T] {
//..
}
}
一个Vec<T>是一个拥有T的集合,一个切片(&[T])是一个借用T的集合。
为Vec实现Deref允许从&Vec<T>到&[T]的隐式解引用,并在自动解引用搜索中包含这种关系。
你可能期望为Vec实现的大多数方法都是为切片实现的。
参见String和&str。
动机
所有权和借用是Rust语言的关键方面。 数据结构必须正确说明这些语义,以便提供良好的用户体验。 当实现一个拥有其数据的数据结构时,提供该数据的借用视图可以实现更灵活的API。
优势
大多数方法只为借用视图实现,然后它们隐含地对拥有视图可用。
让客户端在借用或拥有数据的所有权之间做出选择。
劣势
只有通过解引用才能使用的方法和trait在边界检查时不被考虑,所以使用这种模式的数据结构的泛型编程会变得很复杂(见Borrow和AsReftrait等)。
讨论
智能指针和集合是类似的:一个智能指针指向一个对象,而一个集合指向许多对象。 从类型系统的角度来看,这两者之间没有什么区别。 如果访问每个数据的唯一途径是通过集合,并且集合负责删除数据(即使在共享所有权的情况下,某种借用视图可能是合适的),那么集合就拥有它的数据。 如果集合拥有它的数据,提供借用数据的视图通常是有用的,这样它就可以被多次引用了。
大多数智能指针(例如,Foo<T>)实现了Deref<Target=T>。
然而,集合通常会解引用到一个自定义的类型。
[T]和str有一些语言支持,但在一般情况下,这是没有必要的。
Foo<T>可以实现Deref<Target=Bar<T>,其中Bar是一个动态大小的类型,&Bar<T>是对Foo<T>中数据的借用视图。
通常,有序集合为Range实现Index,以提供分片语法。目标是借用视图。
参见
Latest commit 66d7e6c on 2 Oct 2021