简体   繁体   English

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

[英]Simple as possible example of returning a mutable reference from your own iterator

This question is related, however it moreso covers the reason why the compiler cannot infer a safe lifetime when returning a mutable reference from Iterator::next , which I think I understand. 这个问题是相关的,但是它更涵盖了为什么编译器在从Iterator::next返回可变引用时无法推断安全生命周期的原因,我想我理解。

My question is:我的问题是:

What are the specific steps you can take when designing your own iterator so that it can produce mutable references?在设计自己的迭代器以生成可变引用时,您可以采取哪些具体步骤? Ultimately, I'm hoping for a concise-as-possible, step-by-step, commented example of both an Iterator and its next implementation that I (and anyone) can go to as a clear reference when they run into this situation.最终,我希望有一个尽可能简洁、分步、注释的Iterator及其next实现的示例,当他们遇到这种情况时,我(和任何人)都可以将其作为明确的参考。 unsafe examples are fine, I imagine they are probably necessary! unsafe例子很好,我想它们可能是必要的!

NOTE: I understand that MutItems is normally the recommended example, however its implementation can be difficult to follow as there isn't any documentation on 1. How the markers work in that situation and 2. What the iterator!注意:我知道MutItems通常是推荐的示例,但是它的实现可能很难遵循,因为没有关于 1. 标记在这种情况下如何工作的任何文档以及 2. iterator!是什么iterator! macro expands to and how it works.宏扩展到以及它是如何工作的。 If you use MutItems as your example could you please clarify these things?如果你使用MutItems作为你的例子,你能澄清这些事情吗?

Here's a way of having a mutable iterator over a hypothetical Point struct.这是一种在假设的Point结构上拥有可变迭代器的方法。 I find it very useful to annotate every unsafe block in a similar fashion, since I'm only shooting myself in the foot if I get it wrong!我发现以类似的方式注释每个unsafe非常有用,因为如果我弄错了,我只会在脚下射击!

The Rust compiler does not know that you will get a different mutable reference every time you advance the iterator. Rust 编译器不知道每次推进迭代器时都会得到不同的可变引用。 This unsafe block is safe because the programmer guarantees that this iterator can never return the same mutable reference twice, or allow any other way to get to the same address.这个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);
}

See also也可以看看

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM