插入和删除
slice 不提供的东西是“insert”和“remove”,所以我们接下来做这些。
insert 需要将目标索引的所有元素向右移动一个。要做到这一点,我们需要使用ptr::copy,它是 C 语言memmove的 Rust 版本。它将一些内存块从一个位置复制到另一个位置,正确处理源和目标重叠的情况(这在这里肯定会发生)。
如果我们在索引i处插入,我们要使用旧的 len 将[i ... len]转移到[i+1 ... len+1]。
pub fn insert(&mut self, index: usize, elem: T) {// 注意:`<=` 是因为我们可以把值插入到任何索引范围 ([0,length-1]) 内的位置之后// 这种情况等同于 pushassert!(index <= self.len, "index out of bounds");if self.cap == self.len { self.grow(); }unsafe {// ptr::copy(src, dest, len) 的含义: "从 dst 复制连续的 len 个元素到 src "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;}}
remove 的行为方式正好相反。我们需要将所有的元素从[i+1 ... len + 1]转移到[i ... len],使用新的 len。
pub fn remove(&mut self, index: usize) -> T {// 注意:使用 `<` 是因为 index 不能删除超出元素下标的范围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}}
