essay | tech | year-summary | about

返回上级菜单

Rust Ownership (2) Reference&Borrowing


日期:2021-04-27T00:00:00Z

Reference

RUST因为只允许同时有一个变量指向一个heap内存中的空间
为了编程的简易性,所以有Reference这个概念

在s1进入函数后,s1并没有被解除与”hello”的关联

fn main() {
    let s1 = String::from("hello");

    let len = calculate_length(&s1);

    println!("The length of '{}' is {}.", s1, len);
}

fn calculate_length(s: &String) -> usize {
    s.len()
}

具体的变量指向,如图所示

Reference使用的变量空间,属于借用(Brrow),所以在被释放后不会影响内存空间

let s1 = String::from("hello");

let len = calculate_length(&s1);

fn calculate_length(s: &String) -> usize { // s is a reference to a String
    s.len()
} // Here, s goes out of scope. But because it does not have ownership of what
  // it refers to, nothing happens.

Reference使用的变量属于借用,不可编辑

fn main() {
    let s = String::from("hello");

    change(&s);
}

fn change(some_string: &String) {
  // !error
  // error[E0596]: cannot borrow `*some_string` as mutable, as it is behind a `&` reference
    some_string.push_str(", world");
}

&mut

解决案
带入&mut


fn main() {
    let mut s = String::from("hello");

    change(&mut s);
}

fn change(some_string: &mut String) {
    some_string.push_str(", world");
}

&mut的限制

在同一个scope内,只允许有且同时有一个&mut

下边的代码会报错

let mut s = String::from("hello");

let r1 = &mut s;
let r2 = &mut s;

// !error
// error[E0499]: cannot borrow `s` as mutable more than once at a time
println!("{}, {}", r1, r2);

下面的是ok的例子

let mut s = String::from("hello");

{
    let r1 = &mut s;
} // r1 goes out of scope here, so we can make a new reference with no problems.

let r2 = &mut s;

因为r1,r2不再被使用
这个代码也没有问题

let mut s = String::from("hello");

let r1 = &s; // no problem
let r2 = &s; // no problem
println!("{} and {}", r1, r2);
// r1 and r2 are no longer used after this point

let r3 = &mut s; // no problem
println!("{}", r3);

但是下面的会报错,因为同时只能有一个&mut

let mut s = String::from("hello");

let r1 = &s; // no problem
let r2 = &s; // no problem
let r3 = &mut s; // BIG PROBLEM
// error
// error[E0502]: cannot borrow `s` as mutable because it is also borrowed as immutable
println!("{}, {}, and {}", r1, r2, r3);

Dangling References

Dangling reference指的是pointer指向一块已经被释放的空间。操作这个pointer的行为是不可预测的

Rust从语言上无法生成一个dangling reference

fn main() {
    let reference_to_nothing = dangle();
}

fn dangle() -> &String {
    let s = String::from("hello");

  // error
  // error[E0106]: missing lifetime specifier
    &s
}

为了防止dangling问题,
上面代码应该用下面方式来返回

fn no_dangle() -> String {
    let s = String::from("hello");

    s
}

Ref

References and Borrowing