插入和删除
切片没有提供 insert
和 remove
方法,所以我们接下来要实现它们。
插入需要将目标索引处的所有元素向右移动一位。为此,我们需要使用 ptr::copy
,它是 C 语言中 memmove
的 Rust 版本。它将一块内存从一个位置复制到另一个位置,并正确处理源和目标重叠的情况(这种情况在这里肯定会发生)。
如果我们在索引 i
处插入,我们希望使用旧的长度将 [i .. len]
移动到 [i+1 .. len+1]
。
pub fn insert(&mut self, index: usize, elem: T) {
// Note: `<=` because it's valid to insert after everything
// which would be equivalent to push.
assert!(index <= self.len, "index out of bounds");
if self.len == self.cap { self.grow(); }
unsafe {
// ptr::copy(src, dest, len): "copy from src to dest len elems"
ptr::copy(
self.ptr.as_ptr().add(index),
self.ptr.as_ptr().add(index + 1),
self.len - index,
);
ptr::write(self.ptr.as_ptr().add(index), elem);
}
self.len += 1;
}
删除的行为方式相反。我们需要使用*新的*长度将 [i+1 .. len + 1]
中的所有元素移动到 [i .. len]
。
pub fn remove(&mut self, index: usize) -> T {
// Note: `<` because it's *not* valid to remove after everything
assert!(index < self.len, "index out of bounds");
unsafe {
self.len -= 1;
let result = ptr::read(self.ptr.as_ptr().add(index));
ptr::copy(
self.ptr.as_ptr().add(index + 1),
self.ptr.as_ptr().add(index),
self.len - index,
);
result
}
}