MST

星途 面试题库

面试题:Rust生成器的状态管理

在Rust生成器实现过程中,生成器需要管理其内部状态。请描述生成器在暂停和恢复执行时,如何正确保存和恢复其状态。假设存在一个生成斐波那契数列的生成器,如何处理其状态以便在多次调用`yield`之间保持连续性?
41.3万 热度难度
编程语言Rust

知识考点

AI 面试

面试题答案

一键面试
  1. 生成器状态管理的一般原理
    • 暂停时保存状态:在Rust中,生成器是通过async fn语法糖来实现(在async/await背后使用了生成器概念)。当生成器执行到yield语句时暂停,生成器的当前栈帧和局部变量等状态信息会被捕获并保存。Rust编译器会自动将生成器函数转换为一个状态机,这个状态机包含了生成器执行过程中的所有状态信息。生成器的局部变量、当前执行位置等都会成为状态机状态的一部分。
    • 恢复时恢复状态:当生成器被恢复执行时(通常是通过调用生成器的resume方法,在async/await场景下,当await点之后恢复执行),状态机从保存的状态中恢复,包括局部变量的值和执行位置。生成器从暂停的yield语句之后继续执行。
  2. 斐波那契数列生成器状态处理示例
    • 斐波那契数列生成器需要保存前两个数(初始值通常为0和1)以便生成下一个数。可以定义一个结构体来管理生成器的状态。
    struct FibonacciGenerator {
        a: u64,
        b: u64,
    }
    impl FibonacciGenerator {
        fn new() -> Self {
            FibonacciGenerator { a: 0, b: 1 }
        }
    }
    // 将生成器实现为迭代器
    impl Iterator for FibonacciGenerator {
        type Item = u64;
        fn next(&mut self) -> Option<Self::Item> {
            let result = self.a;
            let new_b = self.a + self.b;
            self.a = self.b;
            self.b = new_b;
            Some(result)
        }
    }
    
    • 在上述代码中,FibonacciGenerator结构体的ab字段在每次调用next(类似于yield的效果)之间保存了生成斐波那契数列所需的状态。每次调用next时,生成器计算并返回下一个斐波那契数,同时更新ab的值,以便下次调用next时继续生成序列。如果使用async/await风格实现生成器(更接近标准的生成器概念):
    async fn fibonacci_generator() -> impl Stream<Item = u64> {
        let mut a = 0;
        let mut b = 1;
        loop {
            let result = a;
            let new_b = a + b;
            a = b;
            b = new_b;
            yield result;
        }
    }
    
    • 这里async fn定义的生成器,ab作为局部变量,在每次yield暂停和恢复之间,它们的值会被状态机保存和恢复,从而保持生成斐波那契数列的连续性。