Rust笔记【3】

  1. 使用指针的场景:
    1)编译时类型大小未知,用于定义struct中递归引用自身类型。
    2)移动大量数据,避免赋值。
    3)多态

  2. Rust中几种只能指针

Box<T>
Rc<T>
RefCell<T>
  1. Box
    1)b是Box类型,数据存储在堆上。
    2)Box实现了Deref trait,可以像普通引用一样使用(可以用*解引用)
    3)实现了Drop trait,离开作用域自动释放内存。
let a = 5;
let b = Box::new(a);
let b = Box::new(5);

println!("b={}", *b); // 解引用使用b
println!("b={}", b); // 使用Deref强制类型转换

// 用Box定义递归类型
enum List {
    
    
	Cons(i32, Box<List>),
	Nil,
}
use crate::List::{
    
    Cons, Nil};

fn main() {
    
    
	let list = Cons(1, Box::new( Cons(2, Box::new(Nil)) ) );
}


  1. 重载解引用操作符
use std::ops::Deref;

// 元组结构体定义语法参考《Rust笔记【1】》,定义和实例化都用小括号
struct MyBox<T>(T);

impl<T> Deref for MyBox<T> {
    
    
	type Target = T; // 关联类型
	fn deref(&self) -> &Self::Target {
    
    
	// 这里必须返回&self.0(变量地址,指针),在解引用时,自动调用deref方法,让后再进行解引用操作,
	// deref()必须返回地址(指针)
		&self.0
	}
}

impl<T> MyBox<T> {
    
    
	fn new(x: T) -> MyBox<T> {
    
    
		MyBox(x)
	}
}

fn main() {
    
    
	let x = 2;
	let y = MyBox::new(x);

	assert_eq!(2, *y); // *y -> *(y.deref())
  1. Deref强制转换

Deref 强制转换(deref coercions)将实现了Deref trait 的类型的引用转换为另一种类型的引用。例如,
Deref 强制转换可以将&String 转换为&str,因为String 实现了Deref trait 因此可以返回&str。Deref
强制转换是Rust 在函数或方法传参上的一种便利操作,并且只能作用于实现了Deref trait 的类型。当
这种特定类型的引用作为实参传递给和形参类型不同的函数或方法时将自动进行

Rust 在发现类型和trait 实现满足三种情况时会进行Deref 强制转换:
• 当T: Deref<Target=U> 时从&T 到&U。
• 当T: DerefMut<Target=U> 时从&mut T 到&mut U。
• 当T: Deref<Target=U> 时从&mut T 到&U。

  1. Drop trait
    1)在退出作用域时Drop::drop方法自动调用,不能手动调用。
    2)如果要提前释放,调用:std::mem::drop方法
trait Drop {
    
    
	fn drop(&mut self);
}

obj.drop(); // Drop::drop()方法,不能主动调用
drop(obj); // 调研std::mem::drop
  1. Rc指针
use std::rc::Rc; // Rc<T>不在prelude中,显式引入

let a = Rc::new(12);
Rc::strong_count(&a)

let b = Rc::clone(&a);
Rc::weak_count(&a)
  1. RefCell
    选择Box,Rc 或RefCell 的理由:
    • Rc 允许相同数据有多个所有者;Box 和RefCell 有单一所有者。
    • Box 允许在编译时执行不可变或可变借用检查;Rc仅允许在编译时执行不可变借用检查;
    RefCell 允许在运行时执行不可变或可变借用检查。
    • 因为RefCell 允许在运行时执行可变借用检查,所以我们可以在即便RefCell 自身是不可变
    的情况下修改其内部的值。
RefCell<T>
  1. 内部可变性

  2. 使用Weak指针代替Rc指针,避免循环引用

parent: RefCell::new(Weak::new())
parent.borrow().upgrade()

let temp = Rc::new(121);
let w = Rc::downgrade(&temp);

猜你喜欢

转载自blog.csdn.net/yinminsumeng/article/details/134161077