Rust入门-引用借用

一、引用借用,是什么、为什么、怎么用

所有权上篇我们已经讨论过了,所以这篇我们讨论Rust的引用借用

1、引用借用 是什么?

Rust 通过借用(Borrowing) 这个概念来达成上述的目的,获取变量的引用 ,称之为借用(borrowing)。

其实就是指针 ,在Rust叫借用,只不过Rust的借用会比指针的使用更严格一点。

2、为什么要有引用借用

所有权很强大,避免了内存的不安全性,但是也带来了一个新麻烦 : 总是把一个值传来传去来使用它。 传入一个函数,很可能还要从该函数传出去,结果就是语言表达变得非常啰嗦,幸运的是,Rust 提供了新功能解决这个问题。

3、怎么用

我们先来看一个简单的例子

rust 复制代码
fn main() {
    let x = 5;
    let y = &x;//获取了不可变变量x的引用,y本身是不可变的变量

    assert_eq!(5, x);
    assert_eq!(5, *y);//获取引用所指向地址的值,和其它语言类似,通过*来获取
}

这段代码中,y获取了不可变变量x的引用。

那么y不可变 引用,在这个不可变引用一词中,"不可变 "指的是该引用不可以修改 所指向的!一定要主要这个区别。

y 也是一个不可变变量 ,这里的不可变,指的是y不可以指向别的变量 ,或者是说不可以修改y的值,要和不可变引用进行区别

通过一段代码和图来进一步理解

rust 复制代码
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()
}

前面这段代码,效果是这样的

通过 &s1 语法,我们创建了一个指向 s1 的引用 ,但是并不拥有它
因为并不拥有 这个值,当引用离开作用域 后,其指向的值也不会被丢弃

同时,&s1也是一个不可变引用 ,我们不可以修改该引用指向的值,如果我们要修改,就会报错

rust 复制代码
fn main() {
    let s = String::from("hello");

    change(&s);
}

fn change(some_string: &String) {
    some_string.push_str(", world");
}
bash 复制代码
error[E0596]: cannot borrow `*some_string` as mutable, as it is behind a `&` reference
 --> src/main.rs:8:3
  |
8 |   some_string.push_str(", world");
  |   ^^^^^^^^^^^ `some_string` is a `&` reference, so the data it refers to cannot be borrowed as mutable
  |
help: consider changing this to be a mutable reference
  |
7 | fn change(some_string: &mut String) {
  |        

3、可变引用

那我们想通过引用来修改引用指向的值该怎么办,这时候就有可变引用

rust 复制代码
fn main() {
    let mut s = String::from("hello");

    change(&mut s);
}

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

这样就能完成修改。

这里一共有关键的两步

  1. 声明 s 是可变类型
  2. 其次创建一个可变的引用 &mut s 和接受可变引用参数 some_string: &mut
    String 的函数。注意是&mut

接下来我们聊一下可变引用的一些使用注意事项

可变引用同时只能存在一个

rust 复制代码
let mut s = String::from("hello");

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

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

这段代码会报错

bash 复制代码
error[E0499]: cannot borrow `s` as mutable more than once at a time 同一时间无法对 `s` 进行两次可变借用
 --> src/main.rs:5:14
  |
4 |     let r1 = &mut s;
  |              ------ first mutable borrow occurs here 首个可变引用在这里借用
5 |     let r2 = &mut s;
  |              ^^^^^^ second mutable borrow occurs here 第二个可变引用在这里借用
6 |
7 |     println!("{}, {}", r1, r2);
  |                        -- first borrow later used here 第一个借用在这里使用

可变引用与不可变引用不能同时存在

rust 复制代码
let mut s = String::from("hello");

let r1 = &s; // 没问题
let r2 = &s; // 没问题
let r3 = &mut s; // 大问题

println!("{}, {}, and {}", r1, r2, r3);
bash 复制代码
error[E0502]: cannot borrow `s` as mutable because it is also borrowed as immutable
        // 无法借用可变 `s` 因为它已经被借用了不可变
 --> src/main.rs:6:14
  |
4 |     let r1 = &s; // 没问题
  |              -- immutable borrow occurs here 不可变借用发生在这里
5 |     let r2 = &s; // 没问题
6 |     let r3 = &mut s; // 大问题
  |              ^^^^^^ mutable borrow occurs here 可变借用发生在这里
7 |
8 |     println!("{}, {}, and {}", r1, r2, r3);
  |                                -- immutable borrow later used here 不可变借用在这里使用

注意,引用的作用域 s 从创建开始,一直持续到它最后一次使用的地方,这个跟变量的作用域有所不同,变量的作用域从创建持续到某一个花括号 }

给大家一段代码看看,Rust真好玩(手动狗头)

rust 复制代码
fn main() {
  let mut s = String::from("hello, ");
  let mut y=&mut s;
  y.push_str("world");
  println!("{}",y)
}

fn push_str(s: &mut String) {
  s.push_str("world")
}
相关推荐
DongLi0110 小时前
rustlings 学习笔记 -- exercises/05_vecs
rust
番茄灭世神1 天前
Rust学习笔记第2篇
rust·编程语言
shimly1234561 天前
(done) 速通 rustlings(20) 错误处理1 --- 不涉及Traits
rust
shimly1234561 天前
(done) 速通 rustlings(19) Option
rust
@atweiwei1 天前
rust所有权机制详解
开发语言·数据结构·后端·rust·内存·所有权
shimly1234561 天前
(done) 速通 rustlings(24) 错误处理2 --- 涉及Traits
rust
shimly1234561 天前
(done) 速通 rustlings(23) 特性 Traits
rust
shimly1234561 天前
(done) 速通 rustlings(17) 哈希表
rust
shimly1234561 天前
(done) 速通 rustlings(15) 字符串
rust
shimly1234562 天前
(done) 速通 rustlings(22) 泛型
rust