String::insert_str
利用了字符串本质上是Vec<u8>
这一事实.reallocates the underlying buffer, moves all the initial bytes to the end, then adds the new bytes to the beginning美元.
这通常不安全,不能直接添加到Vec
,因为在复制过程中,Vec
不再处于有效状态——数据中存在"漏洞".
这对于String
来说并不重要,因为数据是u8
,u8
不实现Drop
.对于Vec
中任意的T
,没有这样的保证,但是如果你非常小心地跟踪你的状态并正确地清理,你可以做同样的事情——这就是splice
所做的!
预告的整个概念似乎已经被驱除
我想这是因为从性能的Angular 来看,预选Vec
分是个糟糕的主意.如果你需要这么做,天真的情况是直截了当的:
fn prepend<T>(v: Vec<T>, s: &[T]) -> Vec<T>
where
T: Clone,
{
let mut tmp: Vec<_> = s.to_owned();
tmp.extend(v);
tmp
}
这有一个更高的内存使用率,因为我们需要有足够的空间为两份v
.
splice
方法接受一个新值的迭代器和一系列要替换的值.在这种情况下,我们不想替换任何内容,所以我们给出了一个空的索引范围来插入.我们还需要将切片转换为适当类型的迭代器:
let s = &[1, 2, 3];
let mut v = vec![4, 5];
v.splice(0..0, s.iter().cloned());
splice
's implementation is non-trivial,但它能有效地进行我们需要的追踪.删除一个值块后,它将为新值删除该内存块.它还会移动向量的尾部(可能会移动几次,具体取决于输入迭代器).Slice
的Drop
实现确保事物始终处于有效状态.
我更惊讶的是,VecDeque
不支持它,因为它的设计目的是更有效地修改数据的开头和结尾.