Rust~Pin的new
向 Pin::new(&mut my_struct)
中传了一个 MyStruct 实例的引用,但是 Pin::new
需要的参数又是 Ptr,这种转换是怎么做到的
注意,区别于其他语言,Ptr 是一个范型,<Ptr: Deref<Target: Unpin>>
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
方法的要求进行必要的解引用,最终匹配到合适的类型。
示例
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 标准库中,其核心目的是为类型提供可变解引用的能力
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
类型的值时,编译器会自动进行解引用操作。
示例
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
}