不稳定的Rust中有一个新的Pin
类型,RFC已经合并。据说传递引用时它被称为游戏改变者,但我不确定应该如何以及何时应该使用它。
任何人都可以用外行的方式解释它吗?
答案 0 :(得分:9)
在编程中,固定X意味着指示X不要移动。
例如:
Pin
类型是什么? Pin
类型的目的是将对象固定在内存中。
它允许获取对象的地址,并保证只要Pin
的实例存活,该地址将保持有效。
开发它的主要用例是支持 Generators 。
生成器的想法是使用yield
编写一个简单的函数,并让编译器自动将此函数转换为状态机。生成器所携带的状态是需要从一次调用保存到另一次调用的“堆栈”变量。
Pin
旨在修复的生成器的关键难点在于,生成器可能最终存储对其自己的数据成员之一的引用(毕竟,您可以创建对堆栈值的引用)或引用最终由其自己的数据成员拥有的对象(例如,从&T
获得的Box<T>
)。
这是自引用结构的子结构,直到现在需要自定义库(以及许多unsafe
)。自引用结构的问题是,如果结构移动,它包含的引用仍然指向旧内存。
Pin
显然已经解决了这个多年前的Rust问题。作为图书馆类型。它创建了额外的保证,只要存在Pin
,就无法移动固定值。
因此,用法是首先创建所需的结构,随意返回/移动它,然后当你对它在内存中的位置感到满意时初始化固定的引用。
答案 1 :(得分:3)
Pin
类型的一种可能用途是自引用对象; an article by ralfj提供了SelfReferential
结构which would be very complicated without it的示例:
#![feature(pin, arbitrary_self_types, optin_builtin_traits)]
use std::ptr;
use std::mem::Pin;
use std::boxed::PinBox;
use std::marker::Unpin;
struct SelfReferential {
data: i32,
self_ref: *const i32,
}
impl !Unpin for SelfReferential {}
impl SelfReferential {
fn new() -> SelfReferential {
SelfReferential { data: 42, self_ref: ptr::null() }
}
fn init(mut self: Pin<SelfReferential>) {
let this : &mut SelfReferential = unsafe { Pin::get_mut(&mut self) };
// Set up self_ref to point to this.data.
this.self_ref = &mut this.data as *const i32;
}
fn read_ref(mut self: Pin<SelfReferential>) -> Option<i32> {
let this : &mut SelfReferential = unsafe { Pin::get_mut(&mut self) };
// Dereference self_ref if it is non-NULL.
if this.self_ref == ptr::null() {
None
} else {
Some(unsafe { *this.self_ref })
}
}
}
fn main() {
let mut s = PinBox::new(SelfReferential::new());
s.as_pin().init();
println!("{:?}", s.as_pin().read_ref()); // prints Some(42)
}