模块课程(2/2)
参考文献和借用
在 Rust 中,将所有权来回传递给函数可能很乏味。为了解决这个问题,Rust 使用引用 (&)。
创建对值的引用称为借用。
不可变的引用
通过在类型或变量前面加上 & 符号来声明引用。默认情况下,引用是不可变的:它们允许读取值但不能修改它。
fn main() {
let s1 = String::from("hello");
// We pass a reference to s1, not ownership
let len = calculate_length(&s1);
// s1 is still usable here!
println!("The length of '{}' is {}.", s1, len);
}
fn calculate_length(s: &String) -> usize { // s is a reference to a String
s.len()
} // Here, s goes out of scope, but since it doesn't own the value, nothing happens可变引用
如果需要修改借用值,则必须使用带有 &mut 的可变引用。原始变量还必须使用 mut 声明为可变的:
fn main() {
let mut s = String::from("hello");
// We pass a mutable reference
change(&mut s);
println!("{}", s); // Prints "hello, world"
}
fn change(some_string: &mut String) {
some_string.push_str(", world");
}借款规则
为了防止编译时的内存损坏和数据竞争,Rust 强制执行两条基本规则:
- 您可以同时对一个值拥有任意数量的不可变引用 (
&T)。 - 或者您一次可以只拥有一个对某个值的可变引用 (
&mut T)。
您绝对不能在同一范围内混合使用相同值的不可变引用和可变引用:
let mut s = String::from("hello");
let r1 = &s; // Valid
let r2 = &s; // Valid
// let r3 = &mut s; // COMPILATION ERROR! You cannot create &mut s if s is already borrowed as immutable参考范围和非词汇生命周期 (NLL)
从历史上看,引用的范围一直持续到创建它的块的末尾。如今,Rust 的编译器更加智能,这要归功于 非词法生命周期 (NLL):引用的作用域在实际使用的最后一行结束,而不一定在块的末尾。
这使得以下代码完全有效:
let mut s = String::from("hello");
let r1 = &s;
let r2 = &s;
println!("{} and {}", r1, r2); // Last use of r1 and r2. The immutable references expire here!
let r3 = &mut s; // Valid! No active immutable references exist at this point自己尝试一下
使用 & 符号将 s1 的不可变引用传递给calculate_length函数。
显示提示
将 `/* TODO \_/`替换为`&s1` 以传递对字符串的不可变引用。
3 次尝试后可用的解决方案
使变量 s 可变(let mut s)并将可变引用(&mut s)传递给更改函数以允许其修改字符串。
显示提示
使用 `let mut s`代替`let s`并调用`change(&mut s);`。
3 次尝试后可用的解决方案
Declare a variable s containing String::from("Rust"). Create two distinct immutable references r1 and r2 to s, and finally print both references separated by a space using the println! macro.
显示提示
Assign `let r1 = &s;` and `let r2 = &s;` to obtain two immutable references, then print them with `println!("{} {}", r1, r2);`.
3 次尝试后可用的解决方案