Rust 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);       //可变地借用一个可变对象
}

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

已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 1024 设计师:白松林 返回首页