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
}
相关推荐
statistican_ABin1 分钟前
中国宠物经济发展分析报告——基于R语言的2018-2024年宠物市场多维度分析
开发语言·r语言·宠物
烂蜻蜓8 分钟前
Flask入门教程(三十一):实用函数与类API——全局工具函数速查
后端·python·flask
计算机毕设定制辅导-无忧学长9 分钟前
《基于Spring Boot传承之光非遗陶瓷烧造产品交易平台的设计与实现》
java·vue.js·spring boot·后端·毕业设计
Zane199412 分钟前
内存都要回收,为什么JVM偏要把堆分成新生代和老年代
java·后端
Zane199413 分钟前
257 is 257 为什么是 True?小整数缓存背后还藏着一个更容易被忽略的机制
后端·python
matlab代码15 分钟前
基于matlab PCA人脸识别系统【源码63期】
开发语言·matlab
Terra.K16 分钟前
后端开发阶段性总结
java·开发语言·后端
学逆向的19 分钟前
PE——合并节
开发语言·网络安全·pe
是个西兰花22 分钟前
C++11:线程库与线程安全问题
开发语言·c++
点心的游戏开发世界24 分钟前
GDScript 入门笔记(十三):字符串操作
开发语言·笔记·游戏引擎·godot