结论:Vec 内部是"指针 + len + capacity"三元组,push 时若 len 达到 capacity,会分配一块更大的堆内存(通常容量翻倍),把旧元素逐个字节拷贝过去并释放旧内存。扩容是 O(n) 操作,但因翻倍策略,均摊下来 push 是 O(1)。
展开:工程上关注 capacity 主要为了两点:1)性能:预先知道元素数量时用 Vec::with_capacity(n) 一次分配到位,避免多次扩容拷贝;2)正确性:扩容会使指向 Vec 内部元素的裸指针和切片失效——持有 &vec[i] 的不可变借用时再 push 会被借用检查器拒绝,这正是 Rust 在编译期防止迭代器失效的体现。易错点:reserve 只保证容量不小于请求值,实现可能多分配;shrink_to_fit 只是请求而非保证。
let mut v = Vec::with_capacity(1024);
assert_eq!(v.capacity(), 1024);
for i in 0..1024 { v.push(i); } // 全程无扩容
追问方向:为什么不能直接 realloc 原内存(可能需移动)、Vec 与 Box<[T]> 的区别。