- 类型前置 & 表示引用,引用允许变量指向一个值但是不发生所有权转移。
- 引用不占有所有权,所以变量超出作用域之后不会触发
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[..];