第10篇:归属权与借用------Rust的安全保障
作者: 李金雨
联系方式: wbtm2718@qq.com
目标读者: Rust中文编程
核心理念: AI时代必须使用中文编程,母语编程阅读效率极高
1. 开篇引入
本课目标
- 理解什么是归属权(所有权)
- 理解Rust所有权的规则
- 掌握借用的概念和使用方法
- 理解借用的规则
- 掌握切片的使用
生活场景引入
想象一下,你有一本漫画书,你是这本书的所有者。当你把这本书借给朋友时,朋友暂时拥有这本书的使用权,但所有权还是你的。朋友看完后,需要把书还给你,你才能继续使用它。
在Rust中,数据也有所有权,就像漫画书一样。当你把数据传递给其他变量或函数时,所有权会转移,就像把书借给朋友一样。
预期成果展示
通过这节课的学习,你将能够:
- 理解Rust的所有权系统
- 正确使用所有权转移
- 掌握借用的方法
- 理解借用的规则
- 正确使用切片
2. 概念讲解
什么是归属权(所有权)
归属权(所有权)是Rust中一个特殊的概念,它决定了谁拥有数据,以及数据何时被释放。
所有权的规则
- 每个值都有一个所有者:每个值在Rust中都有一个变量作为它的所有者
- 同一时间只能有一个所有者:一个值不能有多个所有者
- 所有者离开作用域,值被丢弃:当所有者离开作用域时,值会被自动释放
归属权转移
当你把一个值赋给另一个变量时,所有权会转移:
rust
fn main() {
let 字符串一 = String::from("你好"); // 字符串一拥有"你好"的所有权
let 字符串二 = 字符串一; // 所有权转移给字符串二
// println!("{}", 字符串一); // 错误:字符串一已经失去所有权
println!("{}", 字符串二); // 正确:字符串二拥有所有权
}
借用
借用是指临时使用他人的数据,而不获取所有权。就像借书一样,你可以暂时使用,但书的所有权还是别人的。
不可变借用
不可变借用使用&符号,表示临时读取数据:
rust
fn main() {
fn 打印长度(字符串: &String) {
println!("长度:{}", 字符串.len());
}
let 字符串 = String::from("你好");
打印长度(&字符串); // 不可变借用
println!("{}", 字符串); // 仍然可以使用,因为没有转移所有权
}
可变借用
可变借用使用&mut符号,表示临时修改数据:
rust
fn 修改字符串(字符串: &mut String) {
字符串.push_str(", 世界!");
}
fn main() {
let mut 字符串 = String::from("你好");
修改字符串(&mut 字符串); // 可变借用
println!("{}", 字符串); // 输出:你好, 世界!
}
借用规则
- 同一时间只能有一个可变借用:一个数据不能同时被多个可变借用
- 可变借用和不可变借用不能同时存在:如果有可变借用,就不能有不可变借用
- 借用的生命周期不能超过所有者的生命周期:借用不能比所有者存在更久
rust
fn main() {
let mut 字符串 = String::from("你好");
let 借用一 = &字符串; // 不可变借用
// let 借用二 = &mut 字符串; // 错误:不能同时有不可变借用和可变借用
println!("{}", 借用一);
let 借用二 = &mut 字符串; // 正确:不可变借用已经使用完毕
借用二.push_str(", 世界!");
println!("{}", 借用二);
}
切片
切片是对数据的一部分的引用,它没有所有权。
字符串切片
字符串切片是对字符串的一部分的引用:
rust
fn main() {
let 字符串 = String::from("你好,世界!");
let 切片 = &字符串[0..3]; // 从索引0到2的字符(不包括3)
println!("切片:{}", 切片); // 输出:你好,
let 整个切片 = &字符串[..]; // 整个字符串的切片
println!("整个切片:{}", 整个切片); // 输出:你好,世界!
}
数组切片
数组切片是对数组的一部分的引用:
rust
fn main() {
let 数组 = [1, 2, 3, 4, 5];
let 切片 = &数组[1..4]; // 从索引1到3的元素(不包括4)
println!("切片:{:?}", 切片); // 输出:[2, 3, 4]
let 整个切片 = &数组[..]; // 整个数组的切片
println!("整个切片:{:?}", 整个切片); // 输出:[1, 2, 3, 4, 5]
}
3. 动手实践
基础练习(必做)
-
归属权转移练习 :
rustfn main() { let 字符串一 = String::from("你好"); println!("字符串一:{}", 字符串一); let 字符串二 = 字符串一; // println!("字符串一:{}", 字符串一); // 错误:字符串一已经失去所有权 println!("字符串二:{}", 字符串二); } -
不可变借用练习 :
rustfn main() { fn 打印内容(字符串: &String) { println!("内容:{}", 字符串); } let 字符串 = String::from("你好,世界!"); 打印内容(&字符串); println!("原字符串:{}", 字符串); // 仍然可以使用 } -
可变借用练习 :
rustfn main() { fn 追加内容(字符串: &mut String, 内容: &str) { 字符串.push_str(内容); } let mut 字符串 = String::from("你好"); 追加内容(&mut 字符串, ",世界!"); println!("修改后的字符串:{}", 字符串); }
进阶练习(选做)
-
编写函数交换两个变量的值 :
rustfn main() { fn 交换(a: &mut i32, b: &mut i32) { let 临时 = *a; *a = *b; *b = 临时; } let mut x = 1; let mut y = 2; println!("交换前:x = {}, y = {}", x, y); 交换(&mut x, &mut y); println!("交换后:x = {}, y = {}", x, y); } -
编写函数修改字符串内容 :
rustfn main() { fn 首字母大写(字符串: &mut String) { if let Some(第一个字符) = 字符串.chars().next() { let 大写 = 第一个字符.to_uppercase().to_string(); 字符串.replace_range(0..1, &大写); } } let mut 字符串 = String::from("hello"); println!("修改前:{}", 字符串); 首字母大写(&mut 字符串); println!("修改后:{}", 字符串); }
挑战练习(拓展)
-
编写函数计算向量的总和 :
rustfn main() { fn 计算总和(数字们: &Vec<i32>) -> i32 { let mut 总和 = 0; for 数字 in 数字们 { 总和 += 数字; } 总和 } let 数字们 = vec![1, 2, 3, 4, 5]; let 总和 = 计算总和(&数字们); println!("总和:{}", 总和); println!("原向量:{:?}", 数字们); // 仍然可以使用 }
4. 知识总结
核心概念回顾
- 所有权:数据的拥有者,决定了数据的生命周期
- 所有权转移:当值被赋给另一个变量时,所有权会转移
- 借用:临时使用他人的数据,不获取所有权
- 不可变借用 :使用
&符号,只能读取数据 - 可变借用 :使用
&mut符号,可以修改数据 - 借用规则:同一时间只能有一个可变借用,可变借用和不可变借用不能同时存在
- 切片:对数据一部分的引用,没有所有权
关键代码速查
| 概念 | 代码 | 说明 |
|---|---|---|
| 所有权转移 | let b = a; |
所有权从a转移到b |
| 不可变借用 | &a |
创建一个不可变借用 |
| 可变借用 | &mut a |
创建一个可变借用 |
| 字符串切片 | &s[0..3] |
创建一个字符串切片 |
| 数组切片 | &arr[1..4] |
创建一个数组切片 |
常见错误提醒
- 使用已移动的值:尝试使用已经失去所有权的值
- 借用冲突:同时有多个可变借用,或者同时有可变借用和不可变借用
- 生命周期问题:借用的生命周期超过了所有者的生命周期
- 切片越界:创建的切片超出了数据的范围
5. 课后作业
巩固练习题
- 编写一个程序,演示所有权转移的过程
- 编写一个函数,使用不可变借用来计算字符串的长度
- 编写一个函数,使用可变借用来修改向量的内容
创意编程题
- 发挥你的创意,创建一个程序,使用借用和所有权来管理资源
- 编写一个程序,使用切片来处理字符串和数组
下篇预习提示
下一篇我们将学习"选择模板与模式匹配------处理多种可能性",这是Rust中处理多种情况的强大工具。预习一下:
- 什么是选择模板(枚举)?
- 如何定义枚举?
- 什么是模式匹配?
- 如何使用match表达式?
恭喜你完成了第十篇教程!你已经掌握了Rust的所有权系统,学会了如何安全地管理数据。继续加油,下一篇我们将学习如何处理多种可能性!
学习交流
如果你在学习过程中遇到任何问题,欢迎联系我:
- ** 视频号,"时空系"
- 邮箱: wbtm2718@qq.com
- 其他提示:
- 本人正在开发纯中文编程语言和编译器,有兴趣的可以交流
- 本人正在写一本基于中国母语思维习惯的数学教材,可以让你一年内学完从初中到研究生的数学,而且可以让你快速掌握人工智能的关键数学知识,有兴趣的可以交流
祝你学习愉快!