Rust: Vec类型的into_boxed_slice()方法

比如,我们经常看到Vec类型,但取转其裸指针,经常会看到into_boxed_slice()方法,这是为何?

use std::{fmt, slice};

#[derive(Clone, Copy)]
struct RawBuffer {
    ptr: *mut u8,
    len: usize,
}

impl From> for RawBuffer {
    fn from(vec: Vec) -> Self {
        let slice = vec.into_boxed_slice();
        Self {
            len: slice.len(),
            // into_raw 之后,Box 就不管这块内存的释放了,RawBuffer 需要处理释放
            ptr: Box::into_raw(slice) as *mut u8,
        }
    }
}

其实,你看标准文档,就很清楚,

pub fn into_boxed_slice(self) -> Box<[T], A>

//Converts the vector into Box<[T]>.

//If the vector has excess capacity, its items will be moved into a newly-allocated buffer with exactly the right capacity.

也就是说,转成了Box<[T]>后,指针所指向的类型,更简短了。

let v = vec![1, 2, 3];
let slice = v.into_boxed_slice();
let mut vec = Vec::with_capacity(10);
vec.extend([1, 2, 3]);

assert!(vec.capacity() >= 10);
let slice = vec.into_boxed_slice();
assert_eq!(slice.into_vec().capacity(), 3);

这样,从操作上来讲,更加节省内存空间。

下面是一些进一步测试和应用:

use std::{fmt, slice};
// 从*mut u8 恢复
fn as_ref<'a>(pointer: *mut u8, len: usize) -> &'a [u8] { 
    unsafe { slice::from_raw_parts(pointer, len) } 
}
// 从vec中得到相应的裸指针
fn  get_raw_pointer_from_vec(vec:Vec) ->*mut T{
    let slice = vec.into_boxed_slice();
    Box::into_raw(slice) as *mut T
}

fn main(){

    let mut vec = Vec::with_capacity(10);
    vec.extend([1_u8, 2, 3]);
    //查看into_boxed_slice()后堆上数据的空间情况
    assert!(vec.capacity() >= 10);
    let slice = vec.clone().into_boxed_slice() ;// Box<[u8]> ,clone()不会影响vec值的存在
    assert_eq!(slice.clone().into_vec().capacity(), 3); // slice clone后不会影响slice值存在
    // 转换成&[u8]
    let pointer = get_raw_pointer_from_vec(vec);//获得相应的*mut u8
    let slice_object = as_ref(pointer,slice.len()) ;
    println!("slice_object :{:?}",slice_object);
}

你可能感兴趣的:(rust,开发语言,后端)