往 Vec 里 push 看起来是 O(1),背后其实是「装满就换更大的缓冲区」。这篇把容量变化序列、不同元素大小的起始容量、分配器真实收到的调用次数,以及搬家带来的借用限制都真实跑了一遍。
编译:成功
运行(退出码 0):
new: len=0 cap=0
push 第 1 个后 cap 0 -> 4
push 第 5 个后 cap 4 -> 8
push 第 9 个后 cap 8 -> 16
push 第 17 个后 cap 16 -> 32
push 第 33 个后 cap 32 -> 64
push 第 65 个后 cap 64 -> 128
push 第 129 个后 cap 128 -> 256
push 第 257 个后 cap 256 -> 512
push 第 513 个后 cap 512 -> 1024
push 第 1025 个后 cap 1024 -> 2048 编译:成功
运行(退出码 0):
u8 size_of=1 第一次 push 后 cap=8
u32 size_of=4 第一次 push 后 cap=4
u64 size_of=8 第一次 push 后 cap=4
[u64;16] size_of=128 第一次 push 后 cap=4
1000 字节 size_of=1000 第一次 push 后 cap=4
1024 字节 size_of=1024 第一次 push 后 cap=4
1025 字节 size_of=1025 第一次 push 后 cap=1
5000 字节 size_of=5000 第一次 push 后 cap=1
Vec<()> cap = 18446744073709551615 (usize::MAX = 18446744073709551615)这些起始容量是在当前工具链(rustc 1.98.1)上量到的数字,标准库的实现细节可能随版本变化。
编译:成功
运行(退出码 0):
逐个 push 1000 次(Vec::new): alloc 1 realloc 8 最终 cap 1024
with_capacity(1000) 再 push 1000 次: alloc 1 realloc 0 最终 cap 1000
vec![1,2,3]: cap 3 ; reserve(10) 后 cap 13 (realloc 1 次)
vec![1,2,3] 再 reserve_exact(10): cap 13
cap 8 已满再 reserve(1): cap 16 ; 同样情形 reserve_exact(1): cap 9
with_capacity(100) 存 10 个: cap 100 ; shrink_to_fit 后 cap 10Box 与堆分配的基础见Box<T> 与堆分配。
编译:成功
运行(退出码 0):
cap 4 时地址 0x101581300
push 第 5 个后 cap 8 地址 0x101581170,地址变了
cap 8 里 push 第 5 个:地址没变
源码:
1 | fn main() {
2 | let mut v = vec![1, 2, 3];
3 | let first = &v[0];
4 | v.push(4);
5 | println!("{}", first);
6 | }
编译:失败
error[E0502]: cannot borrow `v` as mutable because it is also borrowed as immutable
--> <实验目录>/src/u56e.rs:4:5
|
3 | let first = &v[0];
| - immutable borrow occurs here
4 | v.push(4);
| ^^^^^^^^^ mutable borrow occurs here
5 | println!("{}", first);
| ----- immutable borrow later used here
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0502`.借用规则见可变借用为什么不能同时存在。