Rust~Pin的new

Pin::new(&mut my_struct) 中传了一个 MyStruct 实例的引用,但是 Pin::new 需要的参数又是 Ptr,这种转换是怎么做到的

注意,区别于其他语言,Ptr 是一个范型,<Ptr: Deref<Target: Unpin>>

rust 复制代码
impl<Ptr: Deref<Target: Unpin>> Pin<Ptr> {
    pub const fn new(pointer: Ptr) -> Pin<Ptr> {
        // SAFETY: the value pointed to is `Unpin`, and so has no requirements
        // around pinning.
        unsafe { Pin::new_unchecked(pointer) }
    }
    ... ...

DerefMut 特征:意味着 P 是一个可以解引用为可变引用的类型

Target 需要实现 Unpin 特征,表示解引用后的目标类型可以安全地被移动

&mut T 类型实现了 DerefMut 特征,它可以解引用为 T 类型。因此,&mut MyStruct 满足 Pin::new 方法中泛型参数 P 的

DerefMut 约束。

Rust 有一个自动解引用机制,当在一个需要特定类型的上下文中使用一个实现了 Deref 或 DerefMut 特征的值时,编译器会自动进行解引用操作,直到得到所需的类型。在 Pin::new(&mut my_struct) 这个调用中,&mut MyStruct 实现了 DerefMut 特征,编译器会根据 Pin::new 方法的要求进行必要的解引用,最终匹配到合适的类型。

示例

rust 复制代码
use std::pin::Pin;

struct MyStruct {
    value: i32,
}

fn main() {
    let mut my_struct = MyStruct { value: 42 };
    // 使用我们定义的 new 函数创建一个 Pin 实例
    let pinned_struct: Pin<&mut MyStruct> = Pin::new(&mut my_struct);

    // 由于 MyStruct 实现了 Unpin 特征,我们可以安全地获取内部可变引用
    let inner_mut = Pin::into_inner(pinned_struct);
    inner_mut.value = 100;

    println!("The updated value is: {}", my_struct.value);
}

&mut T 类型实现了 DerefMut 特征,它可以解引用为 T 类型

引用是一种轻量级的数据类型,它指向另一个值在内存中的位置。&mut T 表示一个可变引用,它允许在不获取值的所有权的情况下,对其所指向的值进行修改。引用的主要目的是提供一种安全、高效的方式来访问和操作内存中的数据。

DerefMut 特征定义在 Rust 标准库中,其核心目的是为类型提供可变解引用的能力

rust 复制代码
pub trait DerefMut: Deref {
    fn deref_mut(&mut self) -> &mut Self::Target;
}

DerefMut 特征继承自 Deref 特征,这意味着实现 DerefMut 的类型也必须实现 Deref。

deref_mut 方法接收一个可变引用 &mut self,并返回一个指向 Self::Target 类型的可变引用。通过实现这个方法,类型可以自定义其可变解引用的行为。

&mut T 实现 DerefMut 特征是为了让可变引用在使用时更加灵活和统一。当使用 &mut T 类型的值时,有时需要直接访问其所指向的 T 类型的值,通过实现 DerefMut 特征,我们可以方便地进行解引用操作。

代码一致性:实现 DerefMut 特征使得 &mut T 类型在使用上与其他实现了 DerefMut 的类型保持一致。例如,可以使用相同的语法来解引用 &mut T 和自定义的智能指针类型。

自动解引用:Rust 的自动解引用机制会根据上下文自动调用 deref_mut 方法,从而简化代码。例如,当在一个需要 T 类型的上下文中使用 &mut T 类型的值时,编译器会自动进行解引用操作。

示例

rust 复制代码
fn main() {
    let mut num = 42;
    let mut ref_num = &mut num;

    // 手动解引用
    let deref_num = *ref_num;
    println!("Dereferenced number: {}", deref_num);

    // 自动解引用
    let result = add_one(ref_num);
    println!("Result after adding one: {}", result);
}

fn add_one(x: i32) -> i32 {
    x + 1
}
相关推荐
Lizhihao_23 分钟前
用TCP实现服务器与客户端的交互
java·服务器·开发语言
小彭努力中1 小时前
13.THREE.HemisphereLight 全面详解(含 Vue Composition 示例)
开发语言·前端·javascript·vue.js·深度学习·数码相机·ecmascript
VinfolHu2 小时前
【JAVA】数据类型与变量:深入理解栈内存分配(4)
java·开发语言
三思而后行,慎承诺2 小时前
Kotlin和JavaScript的对比
开发语言·javascript·kotlin
有梦想的攻城狮4 小时前
spring中的@Configuration注解详解
java·后端·spring·configuration·配置类
言之。4 小时前
Go语言中的错误处理
开发语言·后端·golang
这儿有一堆花4 小时前
JavaScript 代码搜索框
开发语言·javascript·ecmascript
forestsea5 小时前
Java Class类文件结构
java·开发语言
鱼嘻6 小时前
数据结构------C语言经典题目(6)
linux·c语言·开发语言·数据结构·算法
ProgramHan6 小时前
JavaScript性能优化都优化什么
开发语言·javascript·ecmascript