本文简要介绍rust语言中 Struct core::marker::PhantomData
的用法。
用法
pub struct PhantomData<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 PhantomData用法及代码示例
- 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-lang.org大神的英文原创作品 Struct core::marker::PhantomData。非经特殊声明,原始代码版权归原作者所有,本译文未经允许或授权,请勿转载或复制。