推荐阅读原版: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);
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。