9.6 Insert 与 Remove
实现 insert 与 remove
1分钟内可阅读完
译文 · 基于 The Rustonomicon
Insert 与 Remove
原文链接: https://doc.rust-lang.org/nomicon/vec/vec-insert-remove.html
slice 不提供 insert 和 remove,我们来实现。
insert 需要把目标 index 处的所有元素右移一位。为此用 ptr::copy,即 C 的 memmove 的 Rust 版。它把一块内存从一处复制到另一处,正确处理源与目标重叠的情况(此处必然会发生)。
若在 index i 插入,要用旧 len 把 [i .. len] 移到 [i+1 .. len+1]。
pub fn insert(&mut self, index: usize, elem: T) {
// 注意:用 `<=` 因为插入到末尾也合法,等价于 push。
assert!(index <= self.len, "index out of bounds");
if self.len == self.cap { self.grow(); }
unsafe {
// ptr::copy(src, dest, len):"从 src 复制 len 个元素到 dest"
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 行为相反。需要用新 len 把 [i+1 .. len + 1] 移到 [i .. len]。
pub fn remove(&mut self, index: usize) -> T {
// 注意:用 `<` 因为*不能*删除末尾之后
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
}
}