本文簡要介紹rust語言中 Struct std::marker::PhantomData
的用法。
用法
pub struct PhantomData<T> where T: ?Sized;
零大小的類型用於標記 “act like” 他們擁有 T
的東西。
向你的類型添加一個 PhantomData<T>
字段會告訴編譯器你的類型表現得好像它存儲了一個類型為 T
的值,即使它不是真的。在計算某些安全屬性時使用此信息。
有關如何使用 PhantomData<T>
的更多 in-depth 說明,請參閱 the Nomicon 。
一個可怕的筆記👻👻👻
盡管它們都有可怕的名字,但PhantomData
和'phantom types' 是相關的,但並不完全相同。幻像類型參數隻是一個從未使用過的類型參數。在 Rust 中,這經常會導致編譯器報錯,解決方案是通過 PhantomData
的方式添加 “dummy” 使用。
例子
未使用的生命周期參數
PhantomData
最常見的用例可能是具有未使用的生命周期參數的結構,通常作為某些不安全代碼的一部分。例如,這是一個結構體 Slice
,它有兩個 *const T
類型的指針,大概指向某個數組:
struct Slice<'a, T> {
start: *const T,
end: *const T,
}
目的是基礎數據僅在生命周期內有效'a
, 所以Slice
不應該活得更久'a
.但是,此意圖未在代碼中表達,因為沒有使用生命周期'a
因此不清楚它適用於哪些數據。我們可以通過告訴編譯器采取行動來糾正這個問題仿佛 Slice
結構包含一個引用&'a T
:
use std::marker::PhantomData;
struct Slice<'a, T: 'a> {
start: *const T,
end: *const T,
phantom: PhantomData<&'a T>,
}
這反過來也需要注釋 T: 'a
,表明 T
中的任何引用在 'a
的生命周期內都是有效的。
初始化 Slice
時,您隻需為字段 phantom
提供值 PhantomData
:
fn borrow_vec<T>(vec: &Vec<T>) -> Slice<'_, T> {
let ptr = vec.as_ptr();
Slice {
start: ptr,
end: unsafe { ptr.add(vec.len()) },
phantom: PhantomData,
}
}
未使用的類型參數
有時會發生未使用的類型參數,這些參數指示結構是“tied” 的數據類型,即使該數據實際上並未在結構本身中找到。這是一個與 FFI 一起出現的示例。外部接口使用 *mut ()
類型的句柄來引用不同類型的 Rust 值。我們使用包裝句柄的結構ExternalResource
上的幻像類型參數來跟蹤 Rust 類型。
use std::marker::PhantomData;
use std::mem;
struct ExternalResource<R> {
resource_handle: *mut (),
resource_type: PhantomData<R>,
}
impl<R: ResType> ExternalResource<R> {
fn new() -> Self {
let size_of_res = mem::size_of::<R>();
Self {
resource_handle: foreign_lib::new(size_of_res),
resource_type: PhantomData,
}
}
fn do_stuff(&self, param: ParamType) {
let foreign_params = convert_params(param);
foreign_lib::do_stuff(self.resource_handle, foreign_params);
}
}
所有權和掉落檢查
添加類型為 PhantomData<T>
的字段表示您的類型擁有類型為 T
的數據。這反過來意味著當您的類型被刪除時,它可能會刪除一個或多個類型為 T
的實例。這與 Rust 編譯器的 drop check 分析有關。
如果您的結構實際上不是自己的類型的數據T
,最好使用引用類型,比如PhantomData<&'a T>
(理想情況下)或PhantomData<*const T>
(如果沒有生命周期適用),以免表明所有權。
相關用法
- Rust PanicInfo.payload用法及代碼示例
- Rust Path.components用法及代碼示例
- Rust PathBuf.with_capacity用法及代碼示例
- Rust Poll.map用法及代碼示例
- Rust Peekable.peek用法及代碼示例
- Rust Path.is_symlink用法及代碼示例
- Rust Poll.map_ok用法及代碼示例
- Rust Pointer用法及代碼示例
- Rust Path.canonicalize用法及代碼示例
- Rust PartialOrd.partial_cmp用法及代碼示例
- Rust Path.is_relative用法及代碼示例
- Rust Path.file_stem用法及代碼示例
- Rust PermissionsExt.set_mode用法及代碼示例
- Rust Path.to_string_lossy用法及代碼示例
- Rust Path.display用法及代碼示例
- Rust PathBuf.into_os_string用法及代碼示例
- Rust Peekable.next_if用法及代碼示例
- Rust PanicInfo用法及代碼示例
- Rust PathBuf.pop用法及代碼示例
- Rust Path.ancestors用法及代碼示例
- Rust Path用法及代碼示例
- Rust Path.is_dir用法及代碼示例
- Rust Path.strip_prefix用法及代碼示例
- Rust PrefixComponent用法及代碼示例
- Rust PathBuf.set_file_name用法及代碼示例
注:本文由純淨天空篩選整理自rust-lang.org大神的英文原創作品 Struct std::marker::PhantomData。非經特殊聲明,原始代碼版權歸原作者所有,本譯文未經允許或授權,請勿轉載或複製。