PhantomData类型在rust中的用法

hES*_*haN 3 rust phantom-types

我正在查看一些锈迹斑斑的源代码,发现一个名为的数据类型PhantomData。我浏览了锈文件,并在互联网上进行了大量搜索。但是,我无法理解此数据类型在rust中的实际用法。如果可能的话,有人可以简单地向我解释一下吗?

pub struct GPIOD {
   _marker: PhantomData<*const ()>,
}
Run Code Online (Sandbox Code Playgroud)

Opt*_*ach 6

PhantomData结构旨在向编译器发出信号,表明某种类型或生存期正在以某种对编译器透明的方式使用。

引用文档:

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

举例来说,如果我们看一下迭代器类型片[T]std::slice::Iter<'a, T>使用它的声明src按钮,我们将看到它实际上是宣布为:

struct Iter<'a, T: 'a> {
    start: *const T,
    end: *const T,
    _phantom: PhantomData<&'a T>,
}
Run Code Online (Sandbox Code Playgroud)

std频繁使用指针算法以使优化更容易获得(尽管这支持在用户代码中使用指针算法)。在这种情况下,我们需要确保自己确保两个原始指针(不携带生命周期)所指向的数据的寿命超过了结构,因此我们要保持一个PhantomData<&'a T>告诉编译器的行为,就像Iter拥有一个&'a T因此强制执行生命周期规则为了它。


Fre*_*ios 5

除了其他答案之外,我还想添加一个例子。正如另一个答案中所述,PhantomData允许在两个结构之间添加任意生命周期依赖性。

假设您有一个使用消息接收器管理日志工具的结构,以及一个表示向管理器发送消息的实际记录器的结构。尽管记录器不直接依赖于管理器,但管理器必须比记录器寿命更长,以防止发送错误。

天真的代码不会在两个结构之间创建任何依赖关系:

struct LogManager {
    // ...
}

impl LogManager {
    fn logger(&self) -> Logger {
        // returns a fresh `Logger` that holds no reference to `LogManager`...
    }
}

struct Logger {
    // ...
}
Run Code Online (Sandbox Code Playgroud)

现在,如果Logger持有幻像引用,我们可以强制这两个结构之间存在依赖关系:

struct Logger<'a> {
    // ...
    _marker: PhantomData<'a ()>,
}
Run Code Online (Sandbox Code Playgroud)

在 impl 块中:

impl LogManager {
    fn logger(&self) -> Logger {
        Logger {
            // ...
            // Here, `Logger` will have a lifetime dependent of the `LogManager`'s
            // lifetime due to `PhantomData`:
            _marker: PhantomData,
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,没有任何一个实例能够比它的来源地Logger存在得更长久。LogManager