我正在努力理解《铁 rust https://doc.rust-lang.org/std/pin/》中的Pin.

大意是明确的 一百零二

我正在为Box写一个带Pin和不带Pin的函数.我得到了完全相同的结果.如何更改代码才能看到Pin的效果?

use std::fmt::{self, Debug};
use std::pin::Pin;

fn foo_pin<T: Debug>(s: Pin<Box<T>>) {
    let copys = s;
    println!("Hi from Box: {:?}", copys); 
    //println!("Hi from Box: {:?}", s); // ERROR borrow of moved value: `s`
}

fn foo<T: Debug>(s: Box<T>) {
    let copys = s;
    println!("Hi from Box: {:?}", copys); 
    //println!("Hi from Box: {:?}", s); // ERROR borrow of moved value: `s`
}

fn main() {
    // i32
    let b = Box::new(1);
    foo_pin(Pin::new(b));

    let b2 = Box::new(2);
    foo(b2);

    /*
    // &str
    let b = Box::new("abc");
    foo_pin(Pin::new(b));

    let b2 = Box::new("123");
    foo(b2);
    */
}

推荐答案

不是指针不能移动,而是它指向的数据.

例如:

fn foo_pin<T: Debug + Default>(mut s: Pin<Box<T>>) {
    let data_inside: T = std::mem::take(&mut *s); // Can't make this work.
    println!("Hi from Box: {:?}", data_inside);
}

fn foo<T: Debug + Default>(mut s: Box<T>) {
    let data_inside: T = std::mem::take(&mut *s); // Can move the data.
    println!("Hi from Box: {:?}", data_inside);
}

但是,请注意,固定约定仅适用于不实现Unpin的类型,因此不适用于i32&str之类的类型.但是,这些函数是泛型的,不需要Unpin,因此这仍然证明了这一 idea .如果我们需要Unpin,这是可行的:

fn foo_pin<T: Debug + Default + std::marker::Unpin>(mut s: Pin<Box<T>>) {
    let data_inside: T = std::mem::take(&mut *s); // +Works
    println!("Hi from Box: {:?}", data_inside);
}

Rust相关问答推荐

即使参数和结果具有相同类型,fn的TypId也会不同

如何在Rust中为具有多个数据持有者的enum变体编写文档 comments ?

关联类型(类型参数)命名约定

在函数内定义impl和在函数外定义impl的区别

什么时候铁 rust FFI边界上的panic 是未定义的行为?

防止cargo test 中的竞争条件

如何使用reqwest进行异步请求?

为什么特征默认没有调整大小?

如何执行数组文字的编译时串联?

为什么我的trait 对象类型不匹配?

如何获取模块树?

Rust 中 Mutex<> 的深拷贝?

如何在 Rust 中按 char 对字符串向量进行排序?

bcrypt 有长度限制吗?

&str 的编译时拆分是否可能?

为什么会出现无法移出可变引用后面的 `self.x`错误?

Iterator::collect如何进行转换?

你能用 Rust 和 winapi 制作 Windows 桌面应用程序吗?

相互调用的递归异步函数:检测到循环

返回 &str 但不是 String 时,borrow 时间比预期长