插入和删除

切片没有提供 insertremove 方法,所以我们接下来要实现它们。

插入需要将目标索引处的所有元素向右移动一位。为此,我们需要使用 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
    }
}