Phantom Data

在 TiKV 的一次提交里面,同事用了一個(gè) PhantomData 的 marker,當(dāng)時(shí)我就覺得很奇怪,因?yàn)閺膩頉]用過,這是什么東西,做什么用的?瀏覽了一下 doc,發(fā)現(xiàn)主要是干這幾件事情的。

Unused lifetime

在一些 Unsafe 的代碼里面,我們很有可能有一個(gè)沒有用的 lifetime 參數(shù),譬如一個(gè) Slice,我們可能有兩個(gè) start 和 end 的 *const T 指針:

struct Slice<'a, T> {
    start: *const T,
    end: *const T,
}

Slice 的 lifetime 是 'a,也就是不能超過 'a 的生存周期,但實(shí)際 Slice 上面并沒有表現(xiàn)出來,因?yàn)闆]有任何地方使用了這個(gè) 'a,為了解決這個(gè)問題,我們就可以使用 PhantomData:

use std::marker::PhantomData;

struct Slice<'a, T: 'a> {
    start: *const T,
    end: *const T,
    phantom: PhantomData<&'a T>,
}

上面,我們使用了一個(gè) PhantomData,使用了 lifetime 'a,這樣就明確表示 Slice 的生存周期是 'a 了。

Unused Type

對(duì)于一些 generic struct 來說,也有可能自己的 field 并沒有使用 Type Parameter,為了解決這個(gè)問題,我們也可以使用 PhantomData。在 TiKV 的代碼里面,我們就是這么處理的:

pub struct RetryableSendCh<T, C: Sender<T>> {
    ch: C,
    name: &'static str,

    marker: PhantomData<T>,
}

Ownership and Drop check

在 struct 里面加入 PhantomData<T> 也表明我們 own 了 類型 T 的實(shí)際數(shù)據(jù),這就說是當(dāng) struct 被 drop 的時(shí)候,一些類型 T 的實(shí)例也會(huì)被 drop 掉。所以如果我們的 struct 并沒有實(shí)際的 own 類型 T 的數(shù)據(jù),我們需要使用 PhantomData<&'a T> 或者 PhantomData<*const T>。

譬如我們定義一個(gè) Vec:

struct Vec<T> {
    data: *const T, // *const for variance!
    len: usize,
    cap: usize,
}

在上面的例子中,drop 并不會(huì)認(rèn)為 Vec own 類型 T 的任何數(shù)據(jù),也就是說當(dāng) drop 這個(gè) vec 的時(shí)候,相關(guān)的 T 數(shù)據(jù)并不會(huì)被 drop 掉。為了讓 drop checker 認(rèn)為 vec 一定 own 了 T 的數(shù)據(jù),我們可以使用:

use std::marker;

struct Vec<T> {
    data: *const T, // *const for covariance!
    len: usize,
    cap: usize,
    _marker: marker::PhantomData<T>,
}

小結(jié)

Rust 的 PhantomData 對(duì)我是一個(gè)全新的特性,雖然它已經(jīng)存在很久了。對(duì)于這門語言來說,讓我學(xué)習(xí)的地方還有很多。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容