引用与借用
引用与借用
引用
通过
fn main() {
let x: Vec<i32> = vec![1i32, 2, 3];
let y = &x;
println!("x={:?}, y={:?}", x, y);
}
fn main() {
let mut x: i32 = 100;
{
let y: &mut i32 = &mut x;
*y += 2;
}
println!("{}", x);
}
我们再来看下函数调用中借用的用法,定义并使用一个(新的)
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 是对 String 的引用
s.len()
} // 这里,s 离开了作用域。但因为它并不拥有引用值的所有权,
// 所以什么也不会发生
首先,注意变量声明和函数返回值中的所有元组代码都消失了。其次,注意我们传递

借用与引用是一种相辅相成的关系,若
可变借用
fn main() {
let x: Vec<i32> = vec!(1i32, 2, 3);
//可同时有多个不可变借用
let y = &x;
let z = &x;
let m = &x;
//ok
println!("{:?}, {:?}, {:?}, {:?}", x, y, z, m);
}
再次强调下,同一作用域下只能有一个可变借用
- 同一作用域,特定数据最多只有一个可变借用(&mut T
) ,或者2 。 - 同一作用域,特定数据可有
0 个或多个不可变借用(&T) ,但不能有任何可变借用。 - 借用在离开作用域后释放。
- 在可变借用释放前不可访问源变量。
fn main() {
//源变量x可变性
let mut x: Vec<i32> = vec!(1i32, 2, 3);
//只能有一个可变借用
let y = &mut x;
// let z = &mut x; //错误
y.push(100);
//ok
println!("{:?}", y);
//错误,可变借用未释放,源变量不可访问
// println!("{:?}", x);
} //y在此处销毁
借用不改变内存的所有者(Owner
失去所有权的变量不可以被借用(访问
fn main() {
let mut x: Vec<i32> = vec!(1i32, 2, 3);
//更新数组
// push 中对数组进行了可变借用,并在 push 函数退出时销毁这个借用
x.push(10);
{
// 可变借用 1
let mut y = &mut x;
y.push(100);
// 可变借用 2,注意:此处是对 y 的借用,不可再对 x 进行借用,
// 因为 y 在此时依然存活。
let z = &mut y;
z.push(1000);
println!("{:?}", z); //打印: [1, 2, 3, 10, 100, 1000]
} // y 和 z 在此处被销毁,并释放借用。
//访问x正常
println!("{:?}", x); //打印: [1, 2, 3, 10, 100, 1000]
}
注意一个引用的作用域从声明的地方开始一直持续到最后一次使用为止。例如,因为最后一次使用不可变引用在声明可变引用之前,所以如下代码是可以编译的:
let mut s = String::from("hello");
let r1 = &s; // 没问题
let r2 = &s; // 没问题
println!("{} and {}", r1, r2);
// 此位置之后 r1 和 r2 不再使用
let r3 = &mut s; // 没问题
println!("{}", r3);
不可变引用
悬垂引用(Dangling References)
在具有指针的语言中,很容易通过释放内存时保留指向它的指针而错误地生成一个 悬垂指针(dangling pointer
fn dangle() -> &String { // dangle 返回一个字符串的引用
let s = String::from("hello"); // s 是一个新字符串
&s // 返回字符串 s 的引用
} // 这里 s 离开作用域并被丢弃。其内存被释放。
// 危险!
error[E0106]: missing lifetime specifier
--> main.rs:5:16
|
5 | fn dangle() -> &String {
| ^ expected lifetime parameter
|
= help: this function's return type contains a borrowed value, but there is
no value for it to be borrowed from
= help: consider giving it a 'static lifetime
因为
fn no_dangle() -> String {
let s = String::from("hello");
s
}