Rust for循环遍历容器为何无需加&引用也可重复使用
核心认知偏差
你对for循环所有权规则的记忆本身没有错误,但忽略了规则生效的前置条件,同时测试用例刚好触发了Rust的Copy语义例外,才会出现不加&也能复用容器的现象。
具体原因拆解
- 教材描述的「遍历后要复用容器必须加
&借用」,针对的是默认移动语义场景:当容器本身、或容器内的元素没有实现Copytrait时,直接写for item in 容器会拿走容器的所有权,遍历完成后容器就被消耗释放,后续无法再访问。 - 你的测试用例中
haystack是元素为i32的数组:i32是标准的Copy类型,元素实现Copy的数组也会自动实现Copytrait。此时写for item in haystack时,Rust不会拿走原数组的所有权,而是自动拷贝一份数组副本用于遍历,原数组全程保持有效,自然可以反复遍历、甚至最后访问haystack[0]也不会报错。 - 你写的段3、段4效果完全一致是Rust的自动解引用规则导致的:
for item in &haystack遍历拿到的item是&i32类型的引用,段3你手动写*item解引用,段4中match分支的字面量匹配、println!宏打印都会自动对引用做解引用处理,不需要手动写*也能得到相同结果。
验证规则的测试方法
把数组元素换成没有实现Copy的类型(比如String),不加&直接遍历就会触发教材描述的所有权错误,示例代码如下:
fn main() { let haystack = [String::from("1"), String::from("42"), String::from("132")]; // 第一次遍历直接拿走数组所有权 for item in haystack { if item == "42" || item == "132" { println!("{item}: hit"); } } // 放开下面的注释会直接编译报错:borrow of moved value: `haystack` // for item in haystack { // println!("{item}"); // } // 此时必须写 for item in &haystack 做借用遍历,才能复用原容器 }
内容的提问来源于stack exchange,提问作者David Cabanis
相关产品推荐
相关产品推荐

