026 Rust死靈書之實現Vec

linghuyichong發表於2021-05-07

本系列錄製的影片主要放在B站上Rust死靈書學習影片

Rust 死靈書相關的原始碼資料在github.com/anonymousGiga/Rustonomi...

從本節開始,我們用我們在Rust死靈書中學到的知識實現一個Vec。

我們的Vec的定義只要這樣就可以了:

pub Struct MyVec<T> {
    ptr: *mut T,
    cap: usize,
    len: usize,
}

如此定義的問題: 我們此處使用的裸指標ptr其實是想達到可變引用的效果,從安全的角度,不應該有別名,或者通俗一點說,此處我們應該鎖定它的內容和owner。

因此,我們定義一個Unique型別,讓裸指標擁有資料。

Uninque型別定義

Unique型別應該滿足的條件:

  • 對T可變;
  • 擁有型別T的值(用於drop檢查);
  • 如果T是Send/Sync,那Unique就也是Send/Sync的;
  • 指標永遠不為null。

可能的Unique定義如下:

use std::marker::PhantomData;

//1、結構體的定義滿足前兩點
struct Unique<T> {
    ptr: *const T, //指標不可變,指標指向的內容可變
    _marker: PhantomData<T>, //用於drop檢查,如果不加,編譯器會認為,結構體沒有擁有型別T,調不呼叫解構函式都無所謂
}

//2、滿足第三點
unsafe impl<T: Send> Send for Unique<T> {}
unsafe impl<T: Sync> Sync for Unique<T> {}

impl<T> Unique<T> {
    const unsafe fn new_unchecked(ptr: *mut T) -> Self {
        unsafe { Unique { ptr: ptr, _marker: PhantomData} }
    }

    //3、滿足第四點
    fn new(ptr: *mut T) -> Option<Self> {
        if !ptr.is_null() {
            Some(unsafe { Unique { ptr: ptr, _marker: PhantomData} })
        } else {
            None
        }
    }

    fn as_ptr(&self) -> *mut T {
        self.ptr as *mut T
    }
}

新的Vec定義

pub struct MyVec<T> {
    //ptr: *mut T,
    ptr: Unique<T>,
    cap: usize,
    len: usize,
}
本作品採用《CC 協議》,轉載必須註明作者和本文連結
令狐一衝

相關文章