推薦閱讀原版:http://rustbyexample.com/borrow.htmlhtml
不少時候,咱們須要訪問一些數據,without taking ownership over it。該怎麼作呢?Rust提供了一個
borrowing機制。代替傳遞對象的值(T
),對象能夠使用引用來傳遞(&T
)。ide
//此函數將是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檢測器來保證引用的指向驗證對象。例如若是對象存在引用,那麼該對象就不能銷燬。函數
&T
用來borrow一些不可變數據的引用,只能讀取數據,不能修改數據。
可修改數據經過&mut T
來引用就能夠對該數據進行讀寫了。ui
#[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); }
運行結果:this
我借了一本韓寒的《三重門》2002版 我借了一本韓寒的《三重門》2014版 [Finished in 0.1s]
當一個數據被borrow時,該數據也會被freez。freez以後咱們就不能修改引用的元素對象了,
直到跳出全部引用做用範圍code
fn main() { let mut _integer = 5i; { let _ref_to_integer = &_integer; //error: cannot assign to `_integer` because it is borrowed _integer = 4 } // 跳出做用域以後咱們就能夠直接操做原始對象了 _integer = 4; }
數據能夠被不修改的borrow無數次,可是當使用不修改的borrow時,原始數據就不能呢個被
可修改的borrow。也就是說,一次只能進行一個可修改的borrow。當跳出做用域以後,原始
的數據才能夠在此修改的borrow。htm
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); }
咱們在使用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); }
還有更多的修改結構字段的方法,參考以下:ip
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); }