Rust : 关于解引用“*”
·
关于解引用*操作符,谨供参考!
一、主要代码
use std::ops::Deref;
fn main() {
model_1();
model_2();
model_3();
model_4();
model_5();
model_6();
model_7();
model_8();
model_9();
}
二、*操作符与常见的引用和解引用
fn model_1(){
let reference:&String = &String::from("hello");
match *reference {
// val :&String
ref val => println!("通过解引用和重新借用获得的值: {:?}", val),
}
}
如果没有ref会如何?自行试一下,便知。
三、*操作符与match和Deref的简单组合
fn model_2(){
model_2_1();
model_2_2();
model_2_3();
fn model_2_1(){
let mybox = MyBox::new(String::from("hello world"));
//*mybox: String */
match *mybox {
ref val => println!("通过解引用和重新借用获得的值: {:?}", val),
}
println!("mybox:{:?}",mybox);
}
// 为什么这里不能是&MyBox(val),只能是MyBox(val)? 感觉类型不匹配呀!
fn model_2_2(){
let mybox = MyBox::new(String::from("hello world"));
let ref_mybox = &mybox;
// ref_mybox: &MyBox<String>
match ref_mybox {
//val:&String
MyBox(val) => println!("通过解引用和重新借用获得的值: {:?}", val),
// error
//&MyBox(val) => println!("通过解引用和重新借用获得的值: {:?}", val),
}
}
// 解引用的找开方式
fn model_2_3(){
let value = MyBox::new(String::from("hello world"));
model_2_3_1(&value);
fn model_2_3_1(value : &MyBox<String>){
match *value {
//val: &MyBox<String>
ref val=> println!("通过解引用和重新借用获得的值: {:?}", val),
// error
//&MyBox(val) => println!("通过解引用和重新借用获得的值: {:?}", val),
// error
//MyBox(val) => println!("通过解引用和重新借用获得的值: {:?}", val),
}
}
}
use std::ops::Deref;
#[derive(Debug)]
struct MyBox<T>(T);
impl<T> Deref for MyBox<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<T: std::fmt::Debug> MyBox<T> {
fn new(x: T) -> MyBox<T> {
MyBox(x)
}
fn my_print(&self) {
match self {
MyBox(x) => println!("{:?}", x),
}
}
}
}
四、*操作: move 所有权的情况
需要注意的是,*操作可能会move所有权,需要慎重。当然也有一些特别情况。后面会具体补充说明。
fn model_3(){
let vec = vec![1, 2, 3];
let v_tmp = &vec; // v_tmp:只是借引用,没有解引用(转移所有权)的权力
//let v_p = *v_tmp; // 去掉注释将报错,error: 转移所有权
println!("vec:{:?}", v_tmp);
}
// *操作: move 所有权
fn model_4(){
let raw = Box::new(String::from("hello world"));
let tmp = *raw; // tmp: String
//println!("raw:{:?}", raw); // 去掉注释将报错,error: 此时raw is moved!
let p = &tmp; // p: &String
println!("box:{:?}", p);
}
// 请问一下:MyBox为什么不可以和Box一样操作?
fn model_5(){
model_5_1();
model_5_2();
fn model_5_1(){
let raw = MyBox::new(String::from("hello world"));
// 下面注释代码一起取消将报错:error
//let tmp = *raw;
//let p = &tmp;
//println!("box:{:?}", p);
let p = &*raw; // p: &String ;此时和分开操作不一样
println!("p:{:?}",p);
}
fn model_5_2(){
let value = String::from("hello world");
let raw = MyBox::new(&value); //raw:MyBox<&String>
let tmp = *raw; // tmp: &String
let p = &**tmp; //p:&str
println!("box:{:?}", p);
}
struct MyBox<T>(T);
impl<T> MyBox<T> {
fn new(x: T) -> MyBox<T> {
MyBox(x)
}
}
impl <T> Deref for MyBox<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.0
}
}
}
五、 *操作符用于赋值
fn model_6(){
let mut p = String::from("hello world");//非 copy 类型
let mut_p = &mut p; // mut_p: &mut String
*mut_p = String::from("Hello World");
println!("mut_p:{:?}", mut_p);
}
六、*操作符与match搭配的复杂情况
1、match与字段进行ref 或ref mut组合搭配
这种情况,不会move所有权。
fn model_7(){
println!("下面是源码,谨供参考!")
//https://doc.rust-lang.org/src/alloc/borrow.rs.html
// impl<B: ?Sized + ToOwned> Clone for Cow<'_, B> {
// fn clone(&self) -> Self {
// match *self {
// Borrowed(b) => Borrowed(b),
// Owned(ref o) => {
// let b: &B = o.borrow();
// Owned(b.to_owned())
// }
// }
// }
// }
}
2、match与"_"搭配
“_”和ref等一样,是个特别的符号。不会move所有权。
fn model_8(){
println!("下面是源码,谨供参考!");
// *self: 为什么可以直接解引用?*self: 字段中没有ref,但有“_”,也可以
//https://doc.rust-lang.org/src/alloc/borrow.rs.html
// impl<B: ?Sized + ToOwned> Cow<'_, B> {
// pub const fn is_borrowed(&self) -> bool {
// match *self {
// Borrowed(_) => true,
// Owned(_) => false,
// }
// }
// pub fn to_mut(&mut self) -> &mut <B as ToOwned>::Owned {
// match *self {
// Borrowed(borrowed) => {
// *self = Owned(borrowed.to_owned());
// match *self {
// Borrowed(..) => unreachable!(),
// Owned(ref mut owned) => owned,
// }
// }
// Owned(ref mut owned) => owned,
// }
// }
// }
}
fn model_9(){
use std::borrow::Borrow;
use std::ops::Deref;
let dog = Dog::Borrowed("hello world");
model_9_1(&dog);
model_9_2(&dog);
// *dog: 字段中没有ref,但有“_”,也可以
fn model_9_1(dog: &Dog<'_,str>){
match *dog{
Dog::Borrowed(_) => {
println!("A");
}
Dog::Owned(_) => {
println!("B");
}
}
}
// 少了ref,将报错!
fn model_9_2(dog: &Dog<'_,str>){
match *dog{
Dog::Borrowed(_) => {
println!("A");
}
Dog::Owned(ref own) => {
println!("B :{:?}",own);
}
}
}
// 模仿Cow
enum Dog<'a,B:?Sized+'a> where B: ToOwned{
Borrowed(&'a B),
Owned( <B as ToOwned>::Owned),
}
impl<B: ?Sized + ToOwned> Deref for Dog<'_, B> where B::Owned: Borrow<B>,
{
type Target = B;
fn deref(&self) -> &B {
match *self {
Dog::Borrowed(borrowed) => borrowed,
Dog::Owned(ref owned) => owned.borrow(),
}
}
}
}
七、问题
1、类型匹配
在model_2_2()中,为什么这里不能是&MyBox(val),只能是MyBox(val)?
fn model_2_2(){
let mybox = MyBox::new(String::from("hello world"));
let ref_mybox = &mybox;
// ref_mybox: &MyBox<String>
match ref_mybox {
//val:&String
MyBox(val) => println!("通过解引用和重新借用获得的值: {:?}", val),
// error
//&MyBox(val) => println!("通过解引用和重新借用获得的值: {:?}", val),
}
}
为什么上面会用MyBox(val)和匹配&MyBox< String>?思考一下。
2、Box和MyBox的操作的差异
具体在model_4和model_5中。Box可以进行先*后&的分开操作,而MyBox不可以。
具体的不同在于Box中是Unique< T>,而不是和MyBox中T 。
// 说明:Box源码如下:
// pub struct Box<T: ?Sized, A: Allocator = Global>(Unique<T>, A);
更多推荐

所有评论(0)