Rust中如何不使用索引,用迭代器实现嵌套可变遍历?
问题原因
你遇到的报错是Rust借用规则的正常拦截:外层调用&mut xs生成可变迭代器时,已经对整个数组发起了独占可变借用,在这个迭代器的整个生命周期内,不允许任何其他借用(不管可变不可变)指向数组,所以内层再次申请&mut xs必然触发E0499错误。
无索引迭代器实现方案
完全不用索引的前提下,最常用的实现方式是借助标准库的内部可变性容器,针对你示例里的Copy型元素(整数),可以用Cell实现:
use std::cell::Cell; fn main() { // 把数组元素用Cell包裹,获得内部可变性 let xs: [Cell<i32>; 3] = [0, 1, 2].map(Cell::new); // 外层迭代拿到的是&Cell<i32>,属于不可变引用,允许多个同时存在 for x in &xs { // 通过Cell的set方法修改值,不需要可变引用 x.set(x.get() + 1); // 内层可以正常迭代,同样拿到不可变引用 for y in &xs { y.set(y.get() + 1); println!("x={} y={}", x.get(), y.get()); } } }
方案说明
Cell<T>是零开销的内部可变性容器,仅适用于实现了Copytrait的类型,不会带来额外性能损耗- 全程使用迭代器遍历,没有用到任何索引操作,符合要求
- 如果你的数组元素不是Copy类型,可以替换为
RefCell<T>,注意RefCell会在运行时做借用检查,如果你逻辑里同时出现多个可变引用会触发panic,需要自己保证访问安全
补充说明
如果你不想用内部可变性,本质上无法实现同时持有多个可变引用遍历同一数组的需求,这是Rust内存安全规则的硬性限制,哪怕你用索引实现,底层本质上也是每次访问的时候临时生成单个元素的可变引用,不会同时持有多个,和迭代器的借用规则本质是一致的。
内容的提问来源于stack exchange,提问作者qwe
相关产品推荐
相关产品推荐

