Post

04所有权·2引用与借用

介绍rust的一个特性:所有权之引用与借用

引用[20230105]

(一).定义

允许你引用某个值而不取得其所有权

1
2
3
4
5
6
7
8
fn main() {
    let s1 = String::from("hello");
    let len = calculate_length(&s1);//&s1以引用的方式(所有权未转移)传递给数calculate_length
    println!("The length of '{}' is {}.", s1, len);//这里s1可以继续使用
}
fn calculate_length(s: &String) -> usize {//s是对string的引用。上面数调用calculate_lengt(&s1)则,s借用s1变量
    s.len()
}//s离开了作用域不会调用drop。因为它并不拥有引用值的所有权,

引用示意图

04-07

(二).引用的可变性和不可变性

1.引用的不可变性

引用和变量一样默认是不可变的

1
2
3
4
5
6
7
fn main() {
    let s = String::from("hello");
    change(&s);
}
fn change(some_string: &String) {
    some_string.push_str(", world");//cannot borrow `*some_string` as mutable, as it is behind a `&` reference
}

2.可变引用

(1).声明语法:xx: &mut TYPE
1
2
3
4
5
6
7
fn main() {
    let s = String::from("hello");
    change(&s);
}
fn change(some_string: &mut String) {
    some_string.push_str(", world");//现在可正常编译了
}
(2).可变引用的限制
  • 在特定作用域内的变量只能有一个可变引用
1
2
3
4
5
6
fn main() {
    let mut s = String::from("hello");
    let r1 = &mut s;
    let r2 = &mut s;//cannot borrow `s` as mutable more than once at a time
    println!("{}, {}", r1, r2);
}
  • 限制的作用:编译期防止数据竞争(data race)
    • data race成立的三个条件:
      • 两个以上的指针同时访问同一个数据
      • 至少有一个指针用于写入数据
      • 没有同步的机制访问数据
  • 可通过创建新作用域,实现非同时多个可变引用
1
2
3
4
5
6
7
fn main() {
    let mut s = String::from("hello");
    {
        let r1 = &mut s;
    } // r1 在这里离开了作用域,所以我们完全可以创建一个新的引用
    let r2 = &mut s;
}
(3)一个变量不可同时拥有可变引用和不可变引用
1
2
3
4
5
6
7
8
9
10
//不可变引用的用户可不希望在他们的眼皮底下值就被意外的改变了!
//然而,多个不可变引用是可以的,因为没有哪个只能读取数据的人有能力影响其他人读取到的数据。
fn main() {
    let mut s = String::from("hello");
    let r1 = &s; // 没问题
    let r2 = &s; // 没问题
    let r3 = &mut s; //cannot borrow `s` as mutable because it is also borrowed as immutable

    println!("{}, {}, and {}", r1, r2, r3);
}

(三).悬垂引用(Dangling References)

悬垂指针是其指向的内存可能已经被分配给其它持有者

rust可避免悬空引用

1
2
3
4
5
6
7
8
9
fn main() {
    let reference_to_nothing = dangle();//error[E0106]: missing lifetime specifier
}
fn dangle() -> &String {
    let s = String::from("hello");
    &s
}//由于dangle返回的是一个引用(没有发生所有权转移),所以s离开作用域并被丢弃。

//当你拥有一些数据的引用,编译器确保数据不会在其引用之前离开作用域。

(四).读记引用的规则

  • 在任意给定时间、作用域内,要么只有一个 可变引用,要么只有1个或多个不可变引用。不允许同时 存在 可变和 不可变引用
  • 引用必须一直有效(指悬垂引用)

借用[20230105]

将创建一个引用的行为称为 借用(borrowing)(如上:把引用作为函数参数这个行为叫借用)

This post is licensed under CC BY 4.0 by the author.