• 类型前置 & 表示引用,引用允许变量指向一个值但是不发生所有权转移。
  • 引用不占有所有权,所以变量超出作用域之后不会触发 drop 调用。
  • 引用作为函数形参被成为借用(borrowing)

可变引用

  • 针对特定作用域下的特定数据只能创建一个可变引用。如果要创建多个可变引用可以通过大括号创建新的作用域

    let mut s = String::from("hello");
    {
    	let s1 = mut &s;
    }
    let s2 = mut &s;
    
  • 当已经存在不可变引用时,则无法再创建可变引用,下面代码无法编译通过

    let mut s = String::from("hello");
    let s1 = &s;   // OK
    let s2 = &s;   // OK
    let s3 = mut &s; // BIG PROBLEM
    

悬空引用

以下代码是不允许的,无法编译通过

fn main() {
	let s = dangling_string();
}

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

上面代码 s 在函数内部分配,那么在函数执行完成后 s 将被释放,所以返回 s 的引用会造成悬空引用。

引用的规则

  • 任何时间针对一个变量,只能有多个不可变引用或者一个可变引用
  • 引用必须一直有效(生命周期)

分片

分片数据类型没有所有权。分片引用一片连续的序列的集合。

字符串分片

字符串分片是一个引用指向 String 的一部分。

let s = String::from("Hello world!")
let hello = &s[0..5];
let world = &s[6..11];

字符串字面量(&str)是个指向二进制程序一块区域的字符串分片,所以函数声明字符串参数使用 &str 会更通用:

fn main() {
	let s = String::from("hello world");
	let word = first_word(&s[..]);

	let sl = "hello world";

	let w1 = first_word(&sl[..]);
	let w2 = first_word(sl);
}

fn first_word(s: &str) -> &str {
	&s[..]
}

其他分片

let a = [1, 2, 3, 4, 5];
let a1 = &a[..];

相关博文