关于Rust中的自引用:差之毫厘?!
生活随笔
收集整理的這篇文章主要介紹了
关于Rust中的自引用:差之毫厘?!
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
先設計一個自引用類型,然后能過std:mem:swap來觀察其變化:
一、為什么自引用沒有出現預期的問題
use std::mem;#[derive(Debug)] struct SelfRef{name : String,ptr: *const String } fn main() {let name_a = String::from("hello a");let ptr_a = & name_a as *const String;let name_b = String::from("hello_b");let ptr_b = & name_b as *const String;let mut self_a = SelfRef{name:name_a,ptr:ptr_a};//這種不是自引用let mut self_b = SelfRef{name:name_b,ptr:ptr_b};//這種不是自引用println!("--------------before swap :----------------------");println!("self_a :{:?} ",self_a);println!("self_b :{:?} ",self_b);println!("a pointer -> self_a: {:p} self_a_inner_ptr:{:p} ",&self_a,self_a.ptr);println!("b pointer -> self_b: {:p} self_b_inner_ptr:{:p} ",&self_b,self_b.ptr);println!("a value -> self_a.name: {:?} self_a_inner_ptr -> value :{:?} ",&self_a.name,unsafe{&*self_a.ptr});println!("b value -> self_b.name: {:?} self_b_inner_ptr -> value :{:?} ",&self_b.name,unsafe{&*self_b.ptr});mem::swap(&mut self_a, &mut self_b);println!("-------------after swap :------------------------");println!("self_a :{:?} ",self_a);println!("self_b :{:?} ",self_b);println!("a pointer -> self_a: {:p} self_a_inner_ptr:{:p} ",&self_a,self_a.ptr);println!("b pointer -> self_b: {:p} self_b_inner_ptr:{:p} ",&self_b,self_b.ptr);println!("a value -> self_a.name: {:?} self_a_inner_ptr -> value :{:?} ",&self_a.name,unsafe{&*self_a.ptr});println!("b value -> self_b.name: {:?} self_b_inner_ptr -> value :{:?} ",&self_b.name,unsafe{&*self_b.ptr});}看看輸出:
Running `target/debug/playground`Standard Output--------------before swap :---------------------- self_a :SelfRef { name: "hello a", ptr: 0x7ffdd46d6480 } self_b :SelfRef { name: "hello_b", ptr: 0x7ffdd46d6498 } a pointer -> self_a: 0x7ffdd46d64b0 self_a_inner_ptr:0x7ffdd46d6480 b pointer -> self_b: 0x7ffdd46d64f0 self_b_inner_ptr:0x7ffdd46d6498 a value -> self_a.name: "hello a" self_a_inner_ptr -> value :"hello a" b value -> self_b.name: "hello_b" self_b_inner_ptr -> value :"hello_b" -------------after swap :------------------------ self_a :SelfRef { name: "hello_b", ptr: 0x7ffdd46d6498 } self_b :SelfRef { name: "hello a", ptr: 0x7ffdd46d6480 } a pointer -> self_a: 0x7ffdd46d64b0 self_a_inner_ptr:0x7ffdd46d6498 b pointer -> self_b: 0x7ffdd46d64f0 self_b_inner_ptr:0x7ffdd46d6480 a value -> self_a.name: "hello_b" self_a_inner_ptr -> value :"hello_b" b value -> self_b.name: "hello a" self_b_inner_ptr -> value :"hello a"奇怪的是,并沒有出現swap后self_a.ptr所指向的內容為“hello_a”,這個是什么原因呢?
二、 調整代碼,重現自引用的問題
我們調整一下:
use std::mem;#[derive(Debug)] struct SelfRef{name : String,ptr: *const String } fn main() {let name_a = String::from("hello a");let mut self_a = SelfRef{name:name_a,ptr: std::ptr::null()};//先賦值self_a.ptr = &self_a.name as *const String;//再對字段進行賦值,變成真正自引用let name_b = String::from("hello b");let mut self_b = SelfRef{name:name_b,ptr:std::ptr::null()};self_b.ptr = &self_b.name as *const String;println!("--------------before swap :----------------------");println!("self_a :{:?} ",self_a);println!("self_b :{:?} ",self_b);println!("a pointer -> self_a: {:p} self_a_inner_ptr:{:p} ",&self_a,self_a.ptr);println!("b pointer -> self_b: {:p} self_b_inner_ptr:{:p} ",&self_b,self_b.ptr);println!("a value -> self_a.name: {:?} self_a_inner_ptr -> value :{:?} ",&self_a.name,unsafe{&*self_a.ptr});println!("b value -> self_b.name: {:?} self_b_inner_ptr -> value :{:?} ",&self_b.name,unsafe{&*self_b.ptr});mem::swap(&mut self_a, &mut self_b);println!("-------------after swap :------------------------");println!("self_a :{:?} ",self_a);println!("self_b :{:?} ",self_b);println!("a pointer -> self_a: {:p} self_a_inner_ptr:{:p} ",&self_a,self_a.ptr);println!("b pointer -> self_b: {:p} self_b_inner_ptr:{:p} ",&self_b,self_b.ptr);println!("a value -> self_a.name: {:?} self_a_inner_ptr -> value :{:?} ",&self_a.name,unsafe{&*self_a.ptr});println!("b value -> self_b.name: {:?} self_b_inner_ptr -> value :{:?} ",&self_b.name,unsafe{&*self_b.ptr}); }再看輸出:
--------------before swap :---------------------- self_a :SelfRef { name: "hello a", ptr: 0x7ffc13a4c808 } self_b :SelfRef { name: "hello b", ptr: 0x7ffc13a4c858 } a pointer -> self_a: 0x7ffc13a4c800 self_a_inner_ptr:0x7ffc13a4c808 b pointer -> self_b: 0x7ffc13a4c850 self_b_inner_ptr:0x7ffc13a4c858 a value -> self_a.name: "hello a" self_a_inner_ptr -> value :"hello a" b value -> self_b.name: "hello b" self_b_inner_ptr -> value :"hello b" -------------after swap :------------------------ self_a :SelfRef { name: "hello b", ptr: 0x7ffc13a4c858 } self_b :SelfRef { name: "hello a", ptr: 0x7ffc13a4c808 } a pointer -> self_a: 0x7ffc13a4c800 self_a_inner_ptr:0x7ffc13a4c858 b pointer -> self_b: 0x7ffc13a4c850 self_b_inner_ptr:0x7ffc13a4c808 a value -> self_a.name: "hello b" self_a_inner_ptr -> value :"hello a" b value -> self_b.name: "hello a" self_b_inner_ptr -> value :"hello b"這下,就看出來了,swap后,self_a結構體中ptr字段指向的內容還是“hello_a”,和原來的預期保持一致了。
三、新的問題來了,如何Pin住?
use std::mem; use std::{marker::PhantomPinned, pin::Pin};#[derive(Debug)] struct SelfRef{name : String,ptr: *const String,_marker: PhantomPinned, //必須打上PIN的標識 }fn main(){let name_a = String::from("hello a");let mut self_a = SelfRef{name:name_a,ptr: std::ptr::null(),_marker: PhantomPinned};let mut self_a = unsafe { Pin::new_unchecked(&mut self_a)};let mut self_a = unsafe { &mut self_a.get_unchecked_mut() }; self_a.ptr = &self_a.name as *const String;let name_b = String::from("hello b");let mut self_b = SelfRef{name:name_b,ptr: std::ptr::null(),_marker: PhantomPinned};let mut self_b = unsafe { Pin::new_unchecked(&mut self_b)};let mut self_b = unsafe { &mut self_b.get_unchecked_mut() }; self_b.ptr = &self_b.name as *const String;println!("--------------before swap <PIN>:----------------------");println!("self_a :{:?} ",self_a);println!("self_b :{:?} ",self_b);println!("a pointer -> self_a: {:p} self_a_inner_ptr:{:p} ",&self_a,self_a.ptr);println!("b pointer -> self_b: {:p} self_b_inner_ptr:{:p} ",&self_b,self_b.ptr);println!("a value -> self_a.name: {:?} self_a_inner_ptr -> value :{:?} ",&self_a.name,unsafe{&*self_a.ptr});println!("b value -> self_b.name: {:?} self_b_inner_ptr -> value :{:?} ",&self_b.name,unsafe{&*self_b.ptr});mem::swap(&mut self_a, &mut self_b);println!("-------------after swap <PIN>:------------------------");println!("self_a :{:?} ",self_a);println!("self_b :{:?} ",self_b);println!("a pointer -> self_a: {:p} self_a_inner_ptr:{:p} ",&self_a,self_a.ptr);println!("b pointer -> self_b: {:p} self_b_inner_ptr:{:p} ",&self_b,self_b.ptr);println!("a value -> self_a.name: {:?} self_a_inner_ptr -> value :{:?} ",&self_a.name,unsafe{&*self_a.ptr});println!("b value -> self_b.name: {:?} self_b_inner_ptr -> value :{:?} ",&self_b.name,unsafe{&*self_b.ptr});看看輸出:
Standard Output--------------before swap <PIN>:---------------------- self_a :SelfRef { name: "hello a", ptr: 0x7fff17773368, _marker: PhantomPinned } self_b :SelfRef { name: "hello b", ptr: 0x7fff177733c8, _marker: PhantomPinned } a pointer -> self_a: 0x7fff17773398 self_a_inner_ptr:0x7fff17773368 b pointer -> self_b: 0x7fff177733f8 self_b_inner_ptr:0x7fff177733c8 a value -> self_a.name: "hello a" self_a_inner_ptr -> value :"hello a" b value -> self_b.name: "hello b" self_b_inner_ptr -> value :"hello b" -------------after swap <PIN>:------------------------ self_a :SelfRef { name: "hello b", ptr: 0x7fff177733c8, _marker: PhantomPinned } self_b :SelfRef { name: "hello a", ptr: 0x7fff17773368, _marker: PhantomPinned } a pointer -> self_a: 0x7fff17773398 self_a_inner_ptr:0x7fff177733c8 b pointer -> self_b: 0x7fff177733f8 self_b_inner_ptr:0x7fff17773368 a value -> self_a.name: "hello b" self_a_inner_ptr -> value :"hello b" b value -> self_b.name: "hello a" self_b_inner_ptr -> value :"hello a"檢查一下,PIN的效果出來了,有了PIN,自引用沒有發生錯亂了,隨著結構體做相應的變動了。
總結
以上是生活随笔為你收集整理的关于Rust中的自引用:差之毫厘?!的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 读 《如何判断自己的文章好坏》
- 下一篇: 从一个被更新后的GTF文件得到geneI