携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第11天,点击查看活动详情
今天要学习的数据结构是集合容器。像其他语言一样,容器例如数组、列表,是非常重要的数据结构。其实,只要是把某些特定的数据封装在某个数据结构中,这个数据结构就能称为容器。例如 Option 封装了存在(Some)或不存在(None)的容器。例如上节学习的 Cow,它也能看作是一个容器,封装了数据 B 的借用(Borrow)或所有权(Owned)。
容器中有一类特别重要,就是集合容器。今天我们学习的主角就是集合容器,例如:
- 字符串、数组、列表、哈希表等
- 切片
- VecDeque 循环缓冲区、LinkedList 双向队列等
今天我们主要学习切片及相关的容器。
01-切片
Rust 中,切片是描述同一类型、长度不定、连续存放的一组数据,用 [T] 表示,它与定长数组的表示方式有点类似 [T; n]。切片是典型的 DST(Dynamically Sized Type),另外一个典型是 trait object。
切片常见的用法有:
- &[T],只读引用
- &mut [T],可变引用
- Box,分配在堆上的切片
课程中有一幅图片,形象地展示了切片与数据结构的关系:
02-切片和 Iterator
切片和 Iterator 经常配合在一起使用。切片是集合数据的视图,而 Iterator 定义了对集合数据的各种操作。切片实现了 iter() 方法,可以获得切片的迭代器,对切片进行迭代。
Iterator trait 最关键的是 next() 方法和 Item 关联类型。
- Item 定义了迭代器取出来的元素类型
- next() 定义了迭代器迭代下一个值的方法,返回 None 时证明迭代器迭代完毕
Rust 中的迭代器一般都支持链式写法,而且迭代器是 lazy 的,即知道运行到 collect 这类方法时才真正开始执行整个链。而且 Rust 对链式调用加入了 inline 优化,以提高其执行效率。
03-&str 是一个特殊的切片
String 是一个特殊的结构,其内部通过 Vec 存储数据。对 String 进行切片,得到的切片为 &str。
String、&String、&str 的关系,通过一幅图来区别:
04-Box<[T]>
Box<[T]> 是一个特殊的结构。它与 Vec的区别如下:
Vec 在栈上的胖指针包含三部分内容,地址、容量和长度;而 Box<[T]> 在栈上的胖指针只包含两部分,地址和长度。
Box<[T]> 与 &[T] 有什么区别呢?
-
Box<[T]> 内存分配在堆上,及栈上胖指针指向的永远是堆中的某块地址。
-
&[T] 指向的地址可能在堆上、也可能在栈上
-
Box<[T]> 具有所有权,而 &[T] 仅是个只读借用
-
目前生成 Box<[T]> 的方式只有一种,即
let v = vec![1, 2, 3, 4]; let b: Box<[i32]> = v.into_boxed_slice(); //
历史文章推荐