一、PhantomData<T>
是一種幻象數據類型,幻象就是無實體,只能看見,無法使用。
1、當我們需要在結構體
S
中加入一個不使用的類型T
,只是爲了告訴編譯器,當前結構體S
和類型T
有某種潛在關係,當drop檢查
的時候可以作爲一種參考。
2、可以改變struct的型變,以便滿足編譯器的檢查要求
二、型變,分爲協變、不變、逆變。
- 協變:A是B的子類型,那麼
Box<A>
是Box<B>
的子類型。 - 不變:A是B的子類型,那麼
Box<A>
和Box<B>
沒有任何關係。 - 逆變:A是B的子類型,那麼
Box<A>
是Box<B>
的父類型。
三、生命週期的型變
1、
'long
是'short
的子類型,寫作'long:'short
2、&'static str
是&'a str
的子類型,寫作&'static str <&'a str>
,協變關係。
四、閉包的型變
1、Fn(T) :在T上是逆變的
2、Fn() -> T :在T上是協變的
3、Fn(T) -> T :在T上是不變的
五、普通類型的型變
1、T:在T上是協變的
2、&'a T:在’a和T上是協變的
3、&'a mut T:在’a上是協變的,在T上是不變
4、*const T:在T上是協變的
5、*mut T:在T上是不變
六、NotNull是一種原生指針的協變版本
沒有NotNull的時候,都是使用
*const T + PhantomData<T>
實現協變結構體,在需要的時候把*const T
轉換爲*mut T
。有了NotNull以後,就不需要了。
NotNull<T>
內部是一個NonZero<*const T>
,*const T
是協變的,所以NotNull<T>
也是協變- NotNull::from:可以將一個可變借用,創建爲
NotNull<T>
- 可變指針:as_ptr() ->
*mut T
- 可變借用:as_mut() ->
&mut T
NotNull 用途:空指針優化,如Option<NotNull<*mut u64>>
,因爲NotNull不可能爲空,所以Option不需要額外的tag來判斷爲空的情況,編譯器在編譯的時候就會優化掉,以節省內存。