0
点赞
收藏
分享

微信扫一扫

Rust RAII &所有权 &引用


文章目录

  • ​​一、RAII​​
  • ​​二、析构函数​​
  • ​​三、所有权和移动​​
  • ​​四、可变性​​
  • ​​五、可变引用​​

一、RAII

RAII源自于现代C++,Rust 强制实行 RAII(Resource Acquisition Is Initiallization,资源获取即初始化),所以任何对象在离开作用域时,它的析构函数(destructor)就被调用,然后它占有的资源就被释放。

这种行为避免了资源泄漏(resource leak),所以你再也不用手动释放内存或者担心内存泄漏(memory leak)!

小示例:

fn main() {
//嵌套作用域:
{
let _box3 = Box::new(4i32); //在堆上分配一个整型数据
} //`_box3`在这里被销毁,内存得到释放
}

二、析构函数

Rust 中的析构函数概念是通过 ​​Drop​​​ trait 提供的。当资源离开作用域,就调用析构函数。
你无需为每种类型都实现 ​​​Drop​​ trait,只要为那些需要自己的析构函数逻辑的类型实现就可以了。

#[derive(Debug)]
struct ToDrop{x:i32,y:i32}


impl Drop for ToDrop{
fn drop(&mut self){
println!("droping!");
}
}

fn main() {
let to_drop = ToDrop{x:12,y:23};
println!("Hello, world!=={:?}",to_drop);
}

// Hello, world!==ToDrop { x: 12, y: 23 }
// droping!

三、所有权和移动

这里主要是涉及在堆中申请的内容,为了极致的性能,指向堆中对象的指针,在进行多次绑定时会涉及到所有权和移动。但是我们也可以对指向堆中对象进行复制,不过这需要实现clone trait。

fn destroy_box(c:Box<u8>){
println!("Droping box !!! {}",c);
}

fn main() {

let x = 12u8;
let y = x;
println!("x is {}, and y is {}", x, y); // rust 对基础数据类型实现了copy,故不存在资源移动

let a = Box::new(255u8);
println!("a contains {},",a);

let b = a;
println!("b contains {}",b);
destroy_box(b);

// println!("a contains {}", a) // 报错!`a`不能访问数据
// println!("b contains: {}", b); // 报错!`b`不能访问数据
}

四、可变性

当所有权转移时,数据的可变性可能发生改变。

fn drop_box(box_i32:Box<i32>){
println!("Droping box contain {}!!!",box_i32);
}


fn borrow_box(borrow_i32:&i32){
println!("Only print value is {}",borrow_i32)
}



fn main() {
let box1 = Box::new(100u8);

let mut box2 = Box::new(200u8);
*box2 = 255u8;
println!("box1 contains is {}",box1);
println!("box2 contains is {}",box2);


let box_i32 = Box::new(100i32);
let stack_i32 = 100i32;

borrow_box(&box_i32);
borrow_box(&stack_i32);
drop_box(box_i32);
}

// box1 contains is 100
// box2 contains is 255
// Only print value is 100
// Only print value is 100
// Droping box contain 100!!!

五、可变引用

可变数据可以使用 ​​&mut T​​​ 进行可变借用。这叫做可变引用(mutable reference),它使
借用者可以读/写数据。相反,​​​&T​​​ 通过不可变引用(immutable reference)来借用数据,
借用者可以读数据而不能更改数据。

#[derive(Clone, Copy)]
struct Book{
author: &'static str,
title: &'static str,
year: u32,
}


fn borrow_book(book:&Book){
println!("I immutable borrowed author =>{} title =>{} year =>{}",
book.author, book.title,book.year);
}


fn new_edition(book:&mut Book){
book.year = 2000;
println!("I mutable borrowed author =>{} title =>{} year =>{}",
book.author, book.title,book.year);
}


fn main(){
let immut_book = Book{
author:"Douglas Hofstadter", //字符串字面量拥有`&'static str`类型
title:"Escher, Bach",
year: 2001,
};

let mut mut_book = immut_book; //创建一个`immutabook`的可变拷贝 #[derive(Clone, Copy)]

borrow_book(&immut_book); //不可变地借用一个不可变对象
borrow_book(&mut_book); //不可变地借用一个可变对象

new_edition(&mut mut_book); //可变地借用一个可变对象
}

如上,禁止可变地借用一个不可变对象,若这样写会编译报错。


举报

相关推荐

0 条评论