fn main() {
let b = Box::new(5);
println!("b = {}",b);
}
//编译时将报错,无法推断出List结构体的具体大小
use crate::List::{Cons, Nil};
enum List{
Cons(i32,List),
Nil,
}
fn main(){
let list = Cons(1, Cons(2, Cons(3, Nil)));
}
此时可以使用Box<T>指针指向嵌套的列表,得到cons list类型的结构体。(指针的内存大小是已知的,但列表的大小是在进行结构体声明时未知的)
示例:
// 此段代码不会报错,因为Box<T>为智能指针,大小固定,编译器可以推断出List类型的大小
use crate::List::{Cons, Nil};
enum List{
Cons(i32, Box<List>),
Nil
}
fn main(){
let list = Cons(1, Box::new(Cons(2, Box::new(Cons(3, Box::new(Nil))))));
}
智能指针类型的变量本身为指针类型,在使用时需要进行解引用来得到其所指向的数据。而解引用需要重载解引用运算符&。而通过实现Deref Trait,能够将类型像引用一样处理。
Deref trait需要实现其定义的deref方法,返回一个内部数据的引用。
示例:
//为Mybox<T>类型实现Deref trait
use std::ops::Deref;
impl<T> Deref for MyBox<T> {
type Target = T;
fn deref(&self) -> &self::Target {
&self.0
}
}
struct MyBox<T>(T);
impl<T> MyBox<T> {
fn new(x: T) -> MyBox<T> {
MyBox(x)
}
}
fn main() {
let x=5;
let y = MyBox::new(x);
assert_eq!(5, x);
assert_eq!(5, *y);
}
Drop trait 类似于c++中的析构函数,在变量离开作用域时调用,清除数据或进行一些其他操作。
实现Drop trait需要实现其drop方法,该方法在变量离开时被调用,完成指定的一些操作。(主要目的为清理该变量拥有的数据)
此外,还可通过std::mem::drop 来在作用域结束前释放变量,std::mem::drop位于prelude中,因此无需显式引入该方法。
示例:
//为CustomSmartPointer结构体实现Drop trait
struct CustomSmartPointer {
data: String,
}
impl Drop for CustomSmartPointer {
fn drop (&mut self){
println!("Droping CustomSmartPointer with Data `{}`", self.data);
}
}
fn main() {
let c = CustomSmartPointer{
data: String::from("my stuff"),
};
drop(c);
let d = CustomSmartPointer{
data: String::from("other stuff"),
};
println!("CustomSmartPointer created.");
}
Rc<T> 用于当我们希望在堆上分配一些数据供程序的多个部分读取,且无法在编译时确定程序的哪一部分会最终结束使用它的时候,如果确实知道哪部分是最后结束使用的话,可以令其成为数据的所有者,正常的所有权规则在编译时生效。
可以通过克隆Rc<T>的方式获取对堆上数据的引用,每次克隆时,引用计数增加1,当一个Rc<T>指针离开作用域时,引用计数减1,而当引用计数为0时,对应的drop方法将会被调用,堆上数据将会被清理。
注意:Rc<T>克隆的结果为不可变引用,rust不允许同时存在多个可变引用。
示例:
use crate::List::{Cons, Nil};
use std::rc::Rc;
enum List {
Cons(i32, Rc<List>),
Nil,
}
fn main(){
let a = Rc::new(Cons(5, Rc::new(Cons(10, Rc::new(Nil)))));
println!("count after creating a = {}", Rc::strong_count(&a));
//Rc::clone得到的是Rc<T>类型的强引用,会影响引用计数
let b = Cons(3, Rc::clone(&a));
println!("count after creating b = {}", Rc::strong_count(&a));
{
let c = Cons(4, Rc::clone(&a));
println!("count after creating c = {}", Rc::strong_count(&a));
}
println!("count after c goes out of scope = {}", Rc::strong_count(&a));
}
use std::cell::RefCell;
trait Messenger {
fn send(&self, msg: &str);
}
struct MockMessenger {
sent_messages: RefCell<Vec<String>>,
}
impl Messager for MockMessenger {
fn send(&self, message: &str) {
//borrow_mut()方法获取的是RefMut<T>类型的智能指针,borrow()方法获取的是Ref<T>类型的智能指针
self.sent_message.borrow_mut().push(String::from(message));
}
}
impl Messenger for MockMessenger {
fn send(&self, message: &str){
//代码将报错,不能同时存在两个可变借用
let mut one_borrow = self.sent_message.borrow_mut();
let mut two_borrow = self.sent_message.borrow_mut();
}
}
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。