从您自己的迭代器返回可变引用的尽可能简单的示例 [英] Simple as possible example of returning a mutable reference from your own iterator

查看:15
本文介绍了从您自己的迭代器返回可变引用的尽可能简单的示例的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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 实现示例当他们遇到这种情况时,可以去作为一个明确的参考.unsafe 例子很好,我想它们可能是必要的!

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. unsafe examples are fine, I imagine they are probably necessary!

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

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! macro expands to and how it works. If you use MutItems as your example could you please clarify these things?

推荐答案

这是一种在假设的 Point 结构上使用可变迭代器的方法.我发现以类似的方式注释每个 unsafe非常很有用,因为如果我弄错了,我只会在自己的脚上开枪!

Here's a way of having a mutable iterator over a hypothetical Point struct. 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!

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

The Rust compiler does not know that you will get a different mutable reference every time you advance the iterator. 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.

#[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);
}

另见

这篇关于从您自己的迭代器返回可变引用的尽可能简单的示例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆