rust - 是否可以使用 Pin 在堆栈而不是堆上创建自引用结构?

标签 rust

是否可以在堆栈上分配自引用结构? pin文档显示了将结构固定在堆上的示例。我按照它写了相应的代码:

pub struct Cont {
    pub f: i32,
    // shall point to 'f' field
    ptr_f: NonNull<i32>,
}

impl Cont {
    pub fn read(&self) -> i32 {
        unsafe { *self.ptr_f.as_ref() }
    }

    pub fn pinned(value: i32) -> Pin<Self> {
        // ensures ptr_f = &f
    }
}

fn main() {
    let a = Cont::pinned(5);
    let b = Cont::pinned(12);

    assert_eq!(a.f, a.read());
    assert_eq!(b.f, b.read());
}

但我不知道如何编写 Cont::pinned 函数,甚至不知道它是否是正确的签名(如果可能的话)。

最佳答案

but I don't know how to write the Cont::pinned function, or even if it's the right signature (if even possible).

Pin<P> 的类型参数始终是指针或引用;一个Pin从不拥有它的数据,除非通过拥有指针类型,如 Box .鉴于您希望将原始值保留在堆栈上,示例中函数的模拟是:

fn pinned(value: i32) -> Pin<&mut Self>;

但这是不可能的,因为函数不能返回对它创建的东西的引用——除非那个东西存储在堆上或静态内存中。所以,如果你要构造一个 Pin对于堆栈分配的值,您必须先创建未固定的值,以便引脚可以引用它。

也许您可能会尝试设计一个 API 来创建一个 Pin通过改变一些已经在堆栈上的数据:

let a: Option<Cont> = None;
let b: Option<Cont> = None;

let a = Cont::pinned(&mut a, 5);
let b = Cont::pinned(&mut b, 12);

但这样一来,该值的生命周期将比 pin 长,您只能在 pin 处于事件状态时强制执行 pin 保证,从而不合理

为了让它听起来像,您需要以某种方式强制在删除 pin 后无法访问原始值。这将导致 API 非常受限。例如:

fn main() {
    // setup_conts creates the pinned Cont values and calls the closure 
    setup_conts(5, 12, |a: Pin<&mut Cont>, b: Pin<&mut Cont>| {
        // a and b can only be used inside this closure
    })
}

关于rust - 是否可以使用 Pin 在堆栈而不是堆上创建自引用结构?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64621062/

相关文章:

rust - 如何使用 Rust 中的 Termion 获取键盘输入?

rust - 值(value)的生命周期与借用的生命周期

rust - 应该如何处理 Rust 中的 Boxed trait 对象?

rust - 为什么不能在同一结构中存储值和对该值的引用?

iterator - 如何在过滤器闭包中使用 Peekable 迭代器?

rust - 如何找出函数(引用)的类型签名?

rust - 遍历多维 BTreeMap

rust - 如何处理包装在Rc <RefCell <>>中的新型枚举的模式匹配?

rust - 编译器表示数据不能在线程之间安全共享,即使数据被包裹在互斥体中

for-loop - 如何在循环内创建向量的向量?