You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现不消耗自身的迭代器,使Fibonacci实例在循环后仍可复用?

问题:如何让斐波那契迭代器不消耗自身实例?

我编写了一段用于学习的Rust代码,实现了生成斐波那契数列的Fibonacci结构体并为其实现Iterator trait:

struct Fibonacci {
    curr: u32,
    next: u32,
}

impl Iterator for Fibonacci {
    type Item = u32;

    fn next(&mut self) -> Option<Self::Item> {
        let current = self.curr;

        self.curr = self.next;
        self.next = current + self.next;
        Some(current)
    }
}

impl Fibonacci {
    fn new() -> Self {
        Fibonacci { curr: 0, next: 1 }
    }

    fn current(&self) -> u32 {
        self.curr
    }
}

fn main() {
    println!("The first four terms of the Fibonacci sequence are: ");
    let fib = Fibonacci::new();
    for i in fib.take(4) {
        println!("> {}", i);
    }
    // println!("cur {}", fib.current()); // *fails*
}

调用fib.take(4)会转移fib的所有权,导致后续调用fib.current()时出现如下错误:

let fib = Fibonacci::new();
         --- move occurs because `fib` has type `Fibonacci`, which does not implement the `Copy` trait
    for i in fib.take(4) {
                  ------- `fib` moved due to this method call
...
     println!("cur {}", fib.current());
                        ^^^^^^^^^^^^^ value borrowed here after move

note: this function takes ownership of the receiver `self`, which moves `fib`

请问如何修改实现,让迭代器不消耗自身实例,使循环后的fib变量仍可正常使用?


解决方案

以下几种方式可以实现需求:

方法一:为Fibonacci实现Clone trait

Fibonacci的字段都是实现了Copy的u32类型,直接派生Clone trait,迭代时克隆原实例,这样原实例的所有权不会被转移:

修改结构体定义:

#[derive(Clone)]
struct Fibonacci {
    curr: u32,
    next: u32,
}

调整main函数,克隆实例进行迭代:

fn main() {
    println!("The first four terms of the Fibonacci sequence are: ");
    let fib = Fibonacci::new();
    for i in fib.clone().take(4) {
        println!("> {}", i);
    }
    println!("cur {}", fib.current()); // 原实例状态保持初始值0,可正常调用
}

如果希望原实例同步迭代进度,只需将fib声明为可变,迭代克隆后的可变实例即可:

fn main() {
    println!("The first four terms of the Fibonacci sequence are: ");
    let mut fib = Fibonacci::new();
    let mut fib_iter = fib.clone();
    for i in fib_iter.take(4) {
        println!("> {}", i);
    }
    fib = fib_iter; // 将迭代后的状态同步回原实例
    println!("cur {}", fib.current()); // 此时curr为3
}

方法二:迭代可变引用而非所有权

利用std::iter::from_mut将可变引用转换为迭代器,take操作针对的是引用而非原实例,既不会转移所有权,还能同步更新原实例的状态:

use std::iter::from_mut;

fn main() {
    println!("The first four terms of the Fibonacci sequence are: ");
    let mut fib = Fibonacci::new();
    for i in from_mut(&mut fib).take(4) {
        println!("> {}", i);
    }
    println!("cur {}", fib.current()); // 原实例状态已更新,curr为3
}

方法三:封装自定义迭代器方法(可选)

为Fibonacci添加一个方法,直接返回自身的可变引用迭代器,让代码更直观:

use std::iter::from_mut;

impl Fibonacci {
    // ... 现有方法 ...
    fn iter(&mut self) -> impl Iterator<Item = u32> + '_ {
        from_mut(self)
    }
}

在main中使用:

fn main() {
    println!("The first four terms of the Fibonacci sequence are: ");
    let mut fib = Fibonacci::new();
    for i in fib.iter().take(4) {
        println!("> {}", i);
    }
    println!("cur {}", fib.current()); // 状态同步更新,curr为3
}

内容的提问来源于stack exchange,提问作者binary01

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 12:15:49