Rust中循环内引用符号(&)的位置对程序有何影响?
Rust中数组迭代时&符号位置的差异解析
这三个示例的输出虽然一致,但执行逻辑、内存消耗和效率存在明显差异,核心区别在于数组的所有权状态、存储位置以及迭代时的元素处理方式,下面逐个拆解:
示例1:无&符号
let arr = [1,2,3]; for n in arr { println!("number {}", n); }
- 类型与所有权:
arr是栈上分配的数组,类型为[i32; 3]。直接在for中使用arr时,会将整个数组的所有权转移给迭代器。 - 元素处理:因为
i32是Copy类型,迭代器会逐个拷贝数组中的元素到循环变量n中。如果数组元素是非Copy类型(比如String),则会直接转移每个元素的所有权,原数组中的元素会被移动,循环结束后原arr无法再被使用。 - 开销:对于小的
Copy类型数组,拷贝开销可以忽略;但如果是大数组或非Copy类型,会产生显著的内存拷贝或所有权转移成本。
示例2:数组定义时加&
let arr = &[1,2,3]; for n in arr { println!("number {}", n); }
- 类型与存储:
arr是一个指向静态数组切片的引用,类型为&[i32]。这里的字面量数组[1,2,3]会被存储在程序的只读数据段(静态存储区),而非栈上。 - 元素处理:迭代这个引用时,迭代器会生成元素的引用
&i32,println!会自动解引用这个引用,所以输出和其他示例一致。整个过程没有所有权转移,也没有元素拷贝。 - 开销:仅传递引用,内存消耗极小,循环结束后
arr仍可正常使用。
示例3:循环中加&
let arr = [1,2,3]; for n in &arr { println!("number {}", n); }
- 类型与所有权:
arr是栈上分配的数组([i32; 3]),&arr会将其转换为切片引用&[i32]。 - 元素处理:迭代逻辑和示例2完全一致,生成元素的引用
&i32,无元素拷贝,也不转移所有权。循环结束后原arr依然可以正常使用。 - 开销:同样仅传递引用,内存消耗低,效率高。
核心差异总结
| 维度 | 示例1 | 示例2 | 示例3 |
|---|---|---|---|
| 所有权状态 | 转移数组所有权,循环后arr不可用 | 不转移所有权,arr可继续使用 | 不转移所有权,arr可继续使用 |
| 元素处理方式 | 拷贝元素(Copy类型)/转移元素所有权(非Copy类型) | 迭代元素引用,无拷贝 | 迭代元素引用,无拷贝 |
| 存储位置 | 数组在栈上 | 数组在只读数据段,arr是引用 | 数组在栈上,迭代时用引用 |
| 内存开销 | 有元素拷贝开销 | 极小(仅引用传递) | 极小(仅引用传递) |
内容的提问来源于stack exchange,提问作者Nack
相关产品推荐
相关产品推荐

