Rust中遍历时常用的引用类型
【摘要】 Rust中遍历时常用的引用类型 1. 不可变引用(&T)- 最常用 大多数场景使用不可变引用:let vec = vec![1, 2, 3, 4, 5];// for循环默认使用不可变引用for item in &vec { // 等价于 for item in vec.iter() println!("{}", item); // item是 &i32 类型}// 直接遍历集合...
Rust中遍历时常用的引用类型
1. 不可变引用(&T)- 最常用
大多数场景使用不可变引用:
let vec = vec![1, 2, 3, 4, 5];
// for循环默认使用不可变引用
for item in &vec { // 等价于 for item in vec.iter()
println!("{}", item); // item是 &i32 类型
}
// 直接遍历集合本身会消耗所有权
// for item in vec { // vec的所有权被移动!
// println!("{}", item);
// }
// 推荐:使用 .iter() 获取不可变引用
for item in vec.iter() {
println!("{}", item);
}
2. 可变引用(&mut T)- 需要修改时使用
需要修改集合元素时使用:
let mut vec = vec![1, 2, 3, 4, 5];
// 使用可变引用遍历并修改
for item in &mut vec { // 等价于 for item in vec.iter_mut()
*item *= 2; // 修改每个元素
}
println!("{:?}", vec); // [2, 4, 6, 8, 10]
区分三种迭代方式:
let vec = vec![1, 2, 3];
// 1. 不可变引用遍历(不消耗所有权)
for item in vec.iter() { // item: &i32
println!("{}", item);
}
println!("vec还能用: {:?}", vec); // vec仍然有效
// 2. 可变引用遍历(不消耗所有权)
let mut vec2 = vec![1, 2, 3];
for item in vec2.iter_mut() { // item: &mut i32
*item *= 2;
}
println!("修改后: {:?}", vec2);
// 3. 消耗所有权遍历(vec会被移动)
let vec3 = vec![1, 2, 3];
for item in vec3.into_iter() { // item: i32
println!("{}", item);
}
// println!("{:?}", vec3); // 错误!vec3已被消耗
3. 常见的遍历场景
遍历向量:
let nums = vec![1, 2, 3, 4, 5];
// 方式1:使用引用(推荐)
for num in &nums {
println!("{}", num);
}
// 方式2:使用索引
for i in 0..nums.len() {
println!("{}", nums[i]);
}
// 方式3:使用 enumerate 获取索引
for (i, num) in nums.iter().enumerate() {
println!("索引{}的值是{}", i, num);
}
遍历哈希表:
use std::collections::HashMap;
let mut scores = HashMap::new();
scores.insert("Alice", 10);
scores.insert("Bob", 20);
// 遍历键值对(使用不可变引用)
for (name, score) in &scores {
println!("{}: {}", name, score);
}
// 遍历并修改值
for score in scores.values_mut() {
*score += 5;
}
遍历数组:
let array = [1, 2, 3, 4, 5];
// 数组实现了 Copy,所以遍历方式更多样
for item in array { // 数组本身会被复制
println!("{}", item);
}
for item in &array { // 使用引用,避免复制
println!("{}", item);
}
4. 智能指针的遍历
遍历包含智能指针的集合:
use std::rc::Rc;
let items = vec![
Rc::new("hello".to_string()),
Rc::new("world".to_string()),
];
// 遍历Rc的引用
for item in &items {
println!("{}", item); // item是 &Rc<String>
}
// 获取内部值的引用
for item in items.iter() {
let s: &String = item.as_ref();
println!("{}", s);
}
5. 遍历中的借用规则
let mut vec = vec![1, 2, 3, 4, 5];
// 正确:在循环中使用不可变引用
for item in &vec {
println!("{}", item);
// vec.push(6); // 错误!不能同时存在可变和不可变借用
}
// 正确:循环结束后再修改
for item in &vec {
println!("{}", item);
}
vec.push(6); // 循环结束后,借用已释放,可以修改
// 可变引用遍历时注意
for item in &mut vec {
*item += 1;
// println!("{:?}", vec); // 错误!可变借用存在时不能使用vec
}
println!("{:?}", vec); // 循环结束后可以访问
总结表
| 遍历场景 | 推荐的引用类型 | 方法 | 备注 |
|---|---|---|---|
| 只读遍历 | 不可变引用 &T |
.iter() 或 &collection |
最常用 |
| 修改元素 | 可变引用 &mut T |
.iter_mut() 或 &mut collection |
需要修改内容时使用 |
| 消耗所有权 | 值本身 T |
.into_iter() |
集合不再需要时使用 |
| 数组遍历 | 不可变引用 &T |
&array |
数组实现Copy,但用引用更好 |
| 智能指针 | 不可变引用 &Rc<T> |
.iter() |
通过 .as_ref() 获取内部值引用 |
最佳实践建议
- 默认使用不可变引用:
for item in &collection或collection.iter() - 需要修改时用可变引用:
for item in &mut collection或collection.iter_mut() - 避免所有权转移:除非明确需要消耗集合,否则不要用
.into_iter() - 注意借用检查:遍历期间不能同时有其他借用
简单记忆口诀
- 只读不写用 & (不可变引用)
- 需要修改用 &mut (可变引用)
- 不再需要用 into (消耗所有权)
- 默认就用 .iter() (最安全)
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)