集合是智能指针
描述
使用Deref
trait将集合视为智能指针,提供拥有
和借用的数据视图。
例子
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
和AsRef
trait等)。
讨论
智能指针和集合是类似的:一个智能指针指向一个对象,而一个集合指向许多对象。 从类型系统的角度来看,这两者之间没有什么区别。 如果访问每个数据的唯一途径是通过集合,并且集合负责删除数据(即使在共享所有权的情况下,某种借用视图可能是合适的),那么集合就拥有它的数据。 如果集合拥有它的数据,提供借用数据的视图通常是有用的,这样它就可以被多次引用了。
大多数智能指针(例如,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