从您自己的迭代器返回可变引用的尽可能简单的示例

min*_*ree 4 iterator reference mutable lifetime rust

这个问题是相关的,但是它更涵盖了为什么编译器在从 返回可变引用时无法推断安全生命周期的原因Iterator::next,我想我理解。

我的问题是:

在设计自己的迭代器以生成可变引用时,您可以采取哪些具体步骤?最终,我希望有一个尽可能简洁、分步、注释的示例,说明 aIterator及其next实现,当他们遇到这种情况时,我(和任何人)可以将其作为明确的参考。unsafe例子很好,我想它们可能是必要的!

注意:我知道这MutItems通常是推荐的示例,但是它的实现可能很难遵循,因为没有关于 1. 标记在那种情况下如何工作以及 2.iterator!宏扩展到什么以及它如何工作的任何文档。如果你用MutItems你的例子,你能澄清这些事情吗?

She*_*ter 6

这是一种在假设Point结构上拥有可变迭代器的方法。我发现以类似的方式注释每个块非常有用unsafe,因为如果我弄错了,我只会在脚下射击!

Rust 编译器不知道每次推进迭代器时都会得到不同的可变引用。这个unsafe块是安全的,因为程序员保证这个迭代器永远不会返回相同的可变引用两次,或者允许任何其他方式到达同一个地址。

#[derive(Debug)]
struct Point {
    x: u8,
    y: u8,
    z: u8,
}

impl Point {
    fn iter_mut(&mut self) -> IterMut {
        IterMut {
            point: self,
            idx: 0,
        }
    }
}

struct IterMut<'a> {
    point: &'a mut Point,
    idx: u8,
}

impl<'a> Iterator for IterMut<'a> {
    type Item = &'a mut u8;

    fn next(&mut self) -> Option<&'a mut u8> {
        let retval = match self.idx {
            0 => &mut self.point.x,
            1 => &mut self.point.y,
            2 => &mut self.point.z,
            _ => return None,
        };

        self.idx += 1;

        // I copied this code from Stack Overflow without paying attention to
        // the prose which described why this code is actually safe.
        unsafe { Some(&mut *(retval as *mut u8)) }
    }
}

fn main() {
    let mut p1 = Point { x: 1, y: 2, z: 3 };

    for x in p1.iter_mut() {
        *x += 1;
    }

    println!("{:?}", p1);
}
Run Code Online (Sandbox Code Playgroud)

也可以看看

  • 谢谢!我最终在自己的用例中完全做到了这一点。对于任何不确定 `transmute` 功能的人,这里是其行为的总结 [来自文档](http://doc.rust-lang.org/std/mem/fn.transmute.html),“不安全地转换值将一种类型的值转换为另一种类型的值。” 在这种情况下,transmute 会推断出正确的返回类型,同时向借用检查器保证可变借用是安全的。 (2认同)