Struct std::marker::PhantomData1.0.0[][src]

pub struct PhantomData<T>
where
    T: ?Sized
;
Expand description

零大小的类型用来标记那些行为像它们拥有一个 T 的东西。

向您的类型添加 PhantomData<T> 字段将告诉编译器,您的类型的行为就像它存储了 T 类型的值一样,即使实际上并非如此。 在计算某些安全属性时会使用此信息。

有关如何使用 PhantomData<T> 的更深入的说明,请参见 the Nomicon

一个可怕的笔记 👻👻👻

尽管它们都有可怕的名称,但 PhantomData 和 phantom 类型是相关的,但并不完全相同。phantom 类型参数只是从未使用过的类型参数。 在 Rust 中,这通常会导致编译器抱怨,而解决方案是通过 PhantomData 添加 “dummy” 用途。

Examples

未使用的生命周期参数

PhantomData 的最常见用例也许是具有未使用的生命周期参数的结构体,通常将其用作某些不安全代码的一部分。 例如,这是一个结构体 Slice,它具有两个 *const T 类型的指针,大概指向某个地方的数组:

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

目的是基础数据仅对生命周期 'a 有效,因此 Slice 不应超过 'a。 但是,此意图未在代码中表达,因为没有使用生命周期 'a,因此尚不清楚它适用于什么数据。 我们可以通过告诉编译器如果 Slice 结构体包含引用 &'a T 来执行 *as 来纠正此问题:

use std::marker::PhantomData;

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

这也需要注解 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,
    }
}
Run

未使用的类型参数

有时可能会发生未使用的类型参数,这些参数指示 “tied” 将结构体数据类型化的数据,即使该数据实际上不是在结构体本身中找到的也是如此。 这是 FFI 出现此情况的示例。 外部接口使用 *mut () 类型的句柄来引用不同类型的 Rust 值。 我们使用包裹句柄的结构体 ExternalResource 上的 phantom 类型参数来跟踪 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);
    }
}
Run

所有权和 drop 检测

添加 PhantomData<T> 类型的字段表示您的类型拥有 T 类型的数据。反过来,这意味着丢弃您的类型时,它可能会丢弃一个或多个 T 类型的实例。 这与 Rust 编译器的 drop check 分析有关。

如果您的结构体实际上并不 拥有T 类型的数据,则最好使用引用类型,例如 PhantomData<&'a T> (ideally) 或 PhantomData<*const T> (如果没有生命周期适用),以免表示所有权。

Trait Implementations

返回值的副本。 Read more

source 执行复制分配。 Read more

使用给定的格式化程序格式化该值。 Read more

返回类型的 “default value”。 Read more

将该值输入给定的 HasherRead more

将这种类型的切片送入给定的 Hasher 中。 Read more

此方法返回 selfother 之间的 OrderingRead more

比较并返回两个值中的最大值。 Read more

比较并返回两个值中的最小值。 Read more

将值限制为一定的时间间隔。 Read more

此方法测试 selfother 值是否相等,并由 == 使用。 Read more

此方法测试 !=

如果存在,则此方法返回 selfother 值之间的顺序。 Read more

此方法测试的内容少于 (对于 selfother),并且由 < 操作员使用。 Read more

此方法测试小于或等于 (对于 selfother),并且由 <= 运算符使用。 Read more

此方法测试大于 (对于 selfother),并且由 > 操作员使用。 Read more

此方法测试是否大于或等于 (对于 selfother),并且由 >= 运算符使用。 Read more

Auto Trait Implementations

Blanket Implementations

获取 selfTypeIdRead more

从拥有的值中一成不变地借用。 Read more

从拥有的值中借用。 Read more

执行转换。

执行转换。

获得所有权后的结果类型。

通常通过克隆从借用数据中创建拥有的数据。 Read more

🔬 This is a nightly-only experimental API. (toowned_clone_into #41263)

recently added

使用借来的数据来替换拥有的数据,通常是通过克隆。 Read more

发生转换错误时返回的类型。

执行转换。

发生转换错误时返回的类型。

执行转换。