详解引用与借用
学习引用与借用,让代码的多个部分能够安全地访问数据而不取得所有权。
详解引用与借用 是 CoddyKit 上的免费 Learn Rust Coding 课时。 这是第 2 节课,共 3 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Learn Rust Coding 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Learn Rust Coding 课程共包含 3 节课。
什么是引用
在 Rust 中,变量拥有自己的数据。但是,如果您需要让代码的其他部分查看甚至修改这些数据,同时又不取得所有权,该怎么办呢?
这时就要用到引用!引用类似于指向某个值的指针,但 Rust 编译器会对其施加严格的规则。
您可以把它想象成透过窗户查看某件物品,而不是拥有这件物品本身。
您的第一个引用
我们使用 & 运算符创建引用。它会创建一个不拥有值的指针。下面来看看它的实际用法:
fn print_length(s: &String) {
println!("The length is: {}", s.len());
}
fn main() {
let message = String::from("Hello, CoddyKit!");
print_length(&message); // Pass a reference
println!("Original message still here: {}", message);
}理解借用
当您创建一个值的引用时,就表示您在借用该值。所有者仍然拥有它,但您可以暂时访问它。
- 借用而不转让:您可以使用借来的数据。
- 不转移所有权:原变量仍然拥有该数据,并会在离开作用域时将其丢弃。
- 安全优先:Rust 的借用规则可以防止数据竞争等常见编程错误。
不可变借用:只读访问
默认情况下,Rust 中的引用是不可变的。这意味着您可以读取它们所指向的数据,但不能修改数据。
这是 Rust 的核心安全特性!如果代码的多个部分都只有只读访问权限,它们就不会意外干扰彼此的数据。
不可变借用实战
这里,calculate_sum 函数接收一个向量的不可变引用。它可以读取元素,但不能添加或删除元素。
fn calculate_sum(numbers: &Vec<i32>) -> i32 {
let mut total = 0;
for num in numbers {
total += num;
}
total
}
fn main() {
let my_numbers = vec![10, 20, 30, 40];
let sum = calculate_sum(&my_numbers); // Immutable borrow
println!("The sum is: {}", sum);
println!("Original vector: {:?}", my_numbers);
}可变借用:修改数据
有时,您需要修改借用的数据。此时可以使用可变引用,表示为 &mut。
可变引用有一条重要规则:同一时间,对于一份特定的数据,您只能拥有一个可变引用。这可以防止数据竞争并确保安全。
使用 &mut 修改数据
add_suffix 函数接收一个指向 String 的可变引用。它可以直接修改原始的 String。
fn add_suffix(text: &mut String) {
text.push_str(" (modified)");
}
fn main() {
let mut my_string = String::from("Original text");
add_suffix(&mut my_string); // Mutable borrow
println!("Modified string: {}", my_string);
}借用的黄金法则
Rust 的编译器会在编译时强制执行这些规则,以保证内存安全:
- 同一时间,对于一份数据,您可以拥有一个可变引用。
- 或者,您可以同时拥有任意数量的不可变引用。
- 存在活跃的不可变引用时,您不能拥有可变引用。
- 引用必须始终有效(不能超过其指向数据的生命周期)。
这些规则可以防止数据竞争,并确保您的程序安全且行为可预测。
相互冲突的借用
这段代码试图同时为 my_value 创建不可变引用和可变引用,这违反了 Rust 的借用规则。它将无法通过编译。
请尝试运行它,看看编译器报出的错误!
fn main() {
let mut my_value = 100;
let r1 = &my_value; // Immutable reference
let r2 = &mut my_value; // Mutable reference (problem here!)
println!("r1: {}", r1);
// println!("r2: {}", r2); // This line would also cause an error if uncommented
}检查您的理解
请思考下面这段 Rust 代码:
fn process_data(data: &mut Vec<i32>) {
data.push(4);
}
fn main() {
let mut numbers = vec![1, 2, 3];
let first_ref = &numbers[0]; // Line A
process_data(&mut numbers); // Line B
println!("First element: {}", first_ref); // Line C
}根据 Rust 的借用规则,哪一行会导致编译时错误?
回顾:引用与借用
做得很好!您已经学习了 Rust 中引用和借用的基础知识:
- 引用(
&)让您可以访问数据而不取得其所有权。 - 借用是创建引用、借出数据访问权限的行为。
- 不可变引用(
&)提供只读访问权限。 - 可变引用(
&mut)提供读写访问权限。 - Rust 严格的借用规则(一个可变引用或多个不可变引用)可以防止数据竞争,并在编译时确保内存安全。
掌握这些概念对于编写安全高效的 Rust 代码至关重要!
常见问题解答
「详解引用与借用」课时是免费的吗?
是的 — 「详解引用与借用」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Learn Rust Coding 课程的其余内容,请升级到 CoddyKit PRO。 Learn Rust Coding 课程共包含 3 节课。
「详解引用与借用」这节课中我会学到什么?
学习引用与借用,让代码的多个部分能够安全地访问数据而不取得所有权。 你通过在浏览器中直接运行的动手代码来练习 Learn Rust Coding,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Learn Rust Coding 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Learn Rust Coding 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 2 节课,共 3 节。
「详解引用与借用」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Learn Rust Coding 课中编写并运行代码吗?
能。每节 Learn Rust Coding 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- 理解 Rust 的所有权模型
- 详解引用与借用
- 用于安全引用的生命周期