前面我们已经实现了一个基础的Vec了,也就是一个栈。我们可以push和pop,也可以自动清理回收,但只有这些还是远远不够的。特别是我们已经有了一个数组,但是没有slice相关的功能,那么有什么办法能实现slice了,这个也非常的容易就是实现
Deref<Target=<T>>
,这样我们的Vec神奇的可以编程了slice。我们只需要使用slice::from_row_ports
。它能够为我们正确的处理空slice,等到后面我们完成了零尺寸类型的支持,它们依然可以完美的配合。
实现Deref和DerefMut
use std::ops::Deref;
impl <T> Deref for Vec<T>{
type Target = [T];
fn deref(&self) -> &[T]{
unsafe {
std::slice::from_raw_parts(self.ptr.as_ptr(), self.len)
}
}
}
顺便我们也把DerefMut一并实现了:
use std::ops:DerefMut;
impl <T> DerefMut for Vec<T> {
fn deref_mut(&mut self) ->&mut [T]{
unsafe{
std::slice::from_row_parts_mut(self.ptr.as_ptr(),self.len);
}
}
}
到了这里,恭喜啊,现在我们有了len
,first
,last
,索引
,分片
,排序
,iter
,iter_mut
以及slice
能提供所有的功能。
但是作为一个Vec怎么能没有插入和删除了,明显是不合理的,首先你得能往Vec中插入元素才能做排序,索引这些了,因此实现Vec的插入和删除也是很重要的,因此我们还是很有必要实现这两个很重要的方法。
实现插入和删除方法
可惜的是slice并没有删除和插入功能,因此我们要实现它们。
首先是插入的基本思路和原理,插入就是把目标位置都向右移动一个位置,这里我们会用到ptr::copy,它能把一块内存拷贝到另一个地方,而且可以正确处理资源和目标内存区域有重叠的情况。如果我们在i这个位置插入一个元素,那么我们就需要把[i..len]移动到[i+1,len],len指的是插入钱的值。
pub insert (&mut self,index::uszie,elem:T){
assert!(index <= self.len,"index out of bounds");
if self.cap == self.len {
self.grow();
}
unsafe {
if index < self.len{
// ptr::copy(src, dest, len): "从src拷贝len个元素到dest"
ptr::copy(self.ptr.offset(index as isize),
self.ptr.offset(index as isize +1),
self.len -index);
}
ptr::write(self.offset(index as isize),elem);
self.len += 1;
}
}
删除则是完全相反的行为,我们只需要把元素[i+1 .. len+1]移动到[i..len]。len是删除后的值。
pub fn remove(&mut self,index:usize) -> T{
// 注意,<是因为我们不能删除所有元素之后的位置
assert!(index < self.len,"index out of bounds");
unsefe{
self.len -= 1;
let result = ptr::read(self.prt.offset(index as isize));
ptr::copy(self.ptr.offset(index as isize + 1),
self.ptr.offset(index as isize),
self.len - index);
result
}
}
最后欢迎大家关注我的公众号:花说编程,是一个rust狂热爱好者和数据库内核工程师