1

推荐阅读原版:http://rustbyexample.com/borrow.html

Borrowing

很多时候,我们需要访问一些数据,without taking ownership over it。该怎么做呢?Rust提供了一个
borrowing机制。代替传递对象的值(T),对象可以使用引用来传递(&T)。

    //此函数将是box的owership
    fn eat_box(boxed_int: Box<int>) {
        println!("destroying box that contains {}", boxed_int);
    }

    //此函数borrow box
    fn peep_inside_box(borrowed_box: &Box<int>) {
        println!("This box contains {}", borrowed_box);
    }


    fn main() {
        //一个int box
        let box_int = box 5;

        //borrow box但是ownership没有改变
        peep_inside_box(&box_int);

        //在此borrow box
        peep_inside_box(&box_int);

        {
            let _ref_to_int: &int = &*box_int;
            //error: cannot move out of `box_int` because it is borrowed
            //eat_box(box_int);
        }

        //放弃box的ownership,销毁box
        eat_box(box_int);
        //销毁之后我们在使用box,就会报错
        println!("destroying box that contains {}", boxed_int);        
    }

编译器总是会通过borrow检测器来保证引用的指向验证对象。例如如果对象存在引用,那么该对象就不能销毁。

Mutability

&T用来borrow一些不可变数据的引用,只能读取数据,不能修改数据。
可修改数据通过&mut T来引用就可以对该数据进行读写了。

#[allow(dead_code)]
struct Book {
    // &'static str 将引用一个只读内存中的字符串
    author: &'static str,
    title : &'static str,
    year  : uint
}

// 此函数将引用一个 book
fn borrow_book (book: &Book) {
    println!("我借了一本{}的《{}》{}版", book.author, book.title, book.year);
}

// 此函数将引用一个可修改 book
fn new_editor (book: &mut Book) {
    book.year = 2014;
}

fn main() {
    let geb = Book {
        author : "韩寒",
        title  : "三重门",
        year   : 2002
    };

    borrow_book(&geb);
    //error: cannot borrow immutable dereference of `&`-pointer as mutable
    //new_editor(&geb);
    // mut_geb 复制了 geb
    let mut mut_geb = geb;

    // borrow 可修改对象
    new_editor(&mut mut_geb);
    // 可修改对象也能被 引用不可修改的函数 borrow
    borrow_book(&mut_geb);
}

运行结果:

我借了一本韩寒的《三重门》2002版
我借了一本韩寒的《三重门》2014版
[Finished in 0.1s]

Freezing(冻结)

当一个数据被borrow时,该数据也会被freez。freez之后我们就不能修改引用的元素对象了,
直到跳出所有引用作用范围

fn main() {
    let mut _integer = 5i;

    {
        let _ref_to_integer = &_integer;
        //error: cannot assign to `_integer` because it is borrowed
        _integer = 4
    }
    // 跳出作用域之后我们就可以直接操作原始对象了
    _integer = 4;
}   

Aliasing

数据可以被不修改的borrow无数次,但是当使用不修改的borrow时,原始数据就不能呢个被
可修改的borrow。也就是说,一次只能进行一个可修改的borrow。当跳出作用域之后,原始
的数据才可以在此修改的borrow。

struct Point { x: int, y: int, z: int }

fn main() {
    let mut point = Point { x: 0, y: 0, z: 0 };

    {
        let borrowed_point = &point;
        let another_borrow = &point;

        // Data can be accessed via the references and the original owner
        println!("Point has coordinates: ({}, {}, {})",
                 borrowed_point.x, another_borrow.y, point.z);

        // Error! Can't borrow point as mutable because it's currently
        // borrowed as immutable
        //let mutable_borrow = &mut point;
        // TODO ^ Try uncommenting this line

        // Immutable references go out of scope
    }

    {
        let mutable_borrow = &mut point;

        // Change data via mutable reference
        mutable_borrow.x = 5;

        // Error! Can't borrow `point` as immutable because it's currently
        // borrowed as mutable
        //let y = &point.y;
        // TODO ^ Try uncommenting this line

        // Error! Can't print, because println! takes an immutable reference
        //println!("Point Z coordinate is {}", point.z);
        // TODO ^ Try uncommenting this line

        // Mutable reference goes out of scope
    }

    // Immutable references to point are allowed again
    println!("Point now has coordinates: ({}, {}, {})",
             point.x, point.y, point.z);
}

The ref pattern

我们在使用pattern match或者通过let解构时,可使用ref引用struct或者tuple的字段。

struct Point { x: int, y: int }

fn main() {mut_point
    let point = Point { x: 0, y: 0 };

    let _copy_of_x = {
        // `ref_to_x` is a reference to the `x` field of `point`
        let Point { x: ref ref_to_x, y: _ } = point;

        // Return a copy of the `x` field of `point`
        *ref_to_x
    };

    // A mutable copy of `point`
    let mut mutable_point = point;
    //通过ref pattern模式来修改元组或结构的字段
    {
        // `ref` can be paired with `mut` to take mutable references
        let Point { x: _, y: ref mut mut_ref_to_y } = mutable_point;

        // Mutate the `y` field of `mutable_point`, via a mutable reference
        *mut_ref_to_y = 1;
    }

    println!("point is ({}, {})", point.x, point.y);
    println!("mutable_point is ({}, {})", mutable_point.x, mutable_point.y);

    let mut tuple = (box 5u, 3u);

    {
        // `ref` can also be paired with `box` to take a mutable reference to
        // the data contained in the box
        let (box ref mut i, _) = tuple;

        *i = 3;
    }

    println!("tuple is {}", tuple);
}

还有更多的修改结构字段的方法,参考如下:

struct Point {
    x: int,
    y: int,
}

impl Point {
    //方法一
    fn change_ref<'s> (&'s mut self) -> &'s mut int{
        &mut self.x
    }
    //方法二
    fn change_ref_2 (&mut self) {
        self.x = 12000;
    }
}

//方法三
fn change_val(point: &mut Point) {
    point.x = 10000;
}

fn main() {
    let point = Point { x: 0, y: 0 };

    let _copy_x = {
        let Point { x: ref ref_to_x, y: _ } = point;

        *ref_to_x
    };

    let mut mut_point = point;

    mut_point.change_ref_2();
    //change_val(&mut mut_point);
    //*mut_point.change_ref() = 1000;

    println!("point is ({}, {})", point.x, point.y);
    println!("mutable_point is ({}, {})", mut_point.x, mut_point.y);

}

天赢金创
338 声望21 粉丝

天赢金创,天赢金创,天赢金创,天赢金创,天赢金创,天赢金创天赢金创,天赢金创