VecDeque 两端 O(1) 的秘密是环形缓冲区:头尾指针在固定缓冲区里绕圈,不搬数据。这篇用 as_slices 和元素地址直接看到「绕回」,并实测头部插入与 Vec 的差距,再看它为什么不能当切片用。
编译:成功
运行(退出码 0):
with_capacity(8): len 0 cap 8
push_back 1..=5: [1, 2, 3, 4, 5] as_slices = ([1, 2, 3, 4, 5], [])
pop_front ×2: [3, 4, 5] as_slices = ([3, 4, 5], [])
再 push_back 6..=9: [3, 4, 5, 6, 7, 8, 9] as_slices = ([3, 4, 5, 6, 7, 8], [9]) (逻辑上连续,物理上绕回了缓冲区开头)
push_front(0): [0, 3, 4, 5, 6, 7, 8, 9] as_slices = ([0, 3, 4, 5, 6, 7, 8], [9]) cap 8
make_contiguous: [0, 3, 4, 5, 6, 7, 8, 9]
之后 as_slices = ([0, 3, 4, 5, 6, 7, 8, 9], []) 编译:成功
运行(退出码 0):
cap 4
逻辑下标 0 值 2 物理槽位 2
逻辑下标 1 值 3 物理槽位 3
逻辑下标 2 值 10 物理槽位 0
逻辑下标 3 值 11 物理槽位 1 编译:成功
运行(退出码 0):
Vec::insert(0) 89.76 ms VecDeque::push_front 0.074 ms
Vec::insert(0) 74.46 ms VecDeque::push_front 0.050 ms
Vec::insert(0) 74.82 ms VecDeque::push_front 0.052 msVec 的扩容见Vec 扩容机制。这里的毫秒数是本机 release 模式的实测,绝对值因机器而异。
编译:成功
运行(退出码 0):
d = [3, 4, 5, 1, 2] d[0] = 3 d[4] = 2 get(9) = None
源码:
1 | use std::collections::VecDeque;
2 | fn main() {
3 | let d: VecDeque<i32> = (1..=5).collect();
4 | let sl: &[i32] = &d;
5 | println!("{:?}", sl);
6 | }
编译:失败
error[E0308]: mismatched types
--> <实验目录>/src/u57d2.rs:4:22
|
4 | let sl: &[i32] = &d;
| ------ ^^ expected `&[i32]`, found `&VecDeque<i32>`
| |
| expected due to this
|
= note: expected reference `&[i32]`
found reference `&VecDeque<i32>`
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0308`.
编译:成功
运行(退出码 0):
make_contiguous().sort() 之后 [1, 2, 3, 4, 5]
VecDeque → Vec: [1, 2, 3, 4, 5]
Vec → VecDeque: [1, 2, 3, 4, 5] (as_slices ([1, 2, 3, 4, 5], []))