Skip to content

1. 引用和借用

1. 引用:允许你获取值的使用权而非所有权。使用符号&传递和接收引用参数。

示例:当以普通的方式,将作用域内的变量以参数的方式传递给某个函数,那么在此之后将无法访问该变量,因为其已经被移动(move)了,使用引用来解决这种情况。

rust
fn main(){
    let s = String::from("hello");
    let len = calculate_length(&s);
  	println!("The length of '{}' is {}.", s, len);//
}

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

2. 借用:创建引用的行为(过程)为借用。借用不获取变量的是所有权,所以也无需返回所有权。

2. 可变引用

当尝试对引用作出修改会发生什么?尝试以下代码:

rust
fn main(){
    let s = String::from("hello");
    let z = change_s(&s);
    pintln!("changed s:{}.", z);//
}

pub fn change_s(s:&String){
   s.push_str(",word")
}

这种操作将收到报错:cannot borrow *sas mutable, as it is behind a& reference,panic信息提示不可对引用变量s作为可变借用。 尝试声明可变引用来解决上述问题,在传递和接受时修改参数签名为mut,诸如:

rust
fn main(){
    let s = String::from("hello");
    let z = change_s(&mut s);
    pintln!("changed s:{}.", z);//"hello,word"
}

pub fn change_s(s:&mut String){
   s.push_str(",word")
}

注意:在同一时间,只能有一个对某一特定数据的可变引用。

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

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

println!("{}, {}, and {}", r1, r2, r3);
shell
$ cargo run
error[E0502]: cannot borrow `s` as mutable because it is also borrowed as immutable
 --> src/main.rs:6:14
  |
4 |     let r1 = &s; // no problem
  |              -- immutable borrow occurs here
5 |     let r2 = &s; // no problem
6 |     let r3 = &mut s; // BIG PROBLEM
  |              ^^^^^^ mutable borrow occurs here
7 | 
8 |     println!("{}, {}, and {}", r1, r2, r3);
  |                                -- immutable borrow later used here

3. slice切片

slice切片是一种没有所有权的数据类型。它允许引用集合中一段连续的元素序列,而不用引用整个集合。

1. 字符串slice

字符串 slicestring slice)是 String 中一部分值的引用,对字符串字面量&str可同样使用slice引用。形式诸如:

rust
let x = String::from("hello word");

//语法&vac[startIndex..endIndex]
let first_word = &x[..5] //当起始索引为0时,可省略

let first_word = &x[6..] //当结束索引为末尾时,可省略

let first_word = &x[5..6] /常规

注意:字符串字面量本身就是slice

2. slice作为参数传递

使用字符串字面量作为参数类型可以同时满足字面量和String两种参数,而不用额外添加新函数。

rust
fn main(){
    let x = "hello word";
    let z = String::from("hello,word");
    
    let x_one = first_word(&x);//
    let z_one = first_word(&z);
   
}
pub fn first_word(s:&str) -> &str{
    for(i,&item) in s.as_bytes().iter().enumerate(){
        if(item == b' '){
            return &s[..i]
        }
    }
    &s[..]
}