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

标签 reference iterator rust mutable lifetime

This question是相关的,但是它还涵盖了编译器在从 Iterator::next 返回可变引用时无法推断出安全生命周期的原因,我想我理解这一点。 p>

我的问题是:

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

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

最佳答案

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

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

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

另见

关于reference - 从您自己的迭代器返回可变引用的尽可能简单的示例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27118398/

相关文章:

c++ - 常量变量与常量引用

c++ - 为什么在取消引用 std::set<T>::iterator 时需要 const?

rust - 有条件地在Rust中对Vec进行排序

concurrency - 将输出 `io::Write` 传递给使用线程的函数的最佳方法是什么?

c++ - 无法将此指针从 const Class<T> 转换为 Class<T>&

performance - 为什么在 F# 中使用引用大值的字段创建记录如此缓慢?

Python如何部分消耗可迭代生成器(没有 `next` )?

rust - std::result::Result <reqwest::Response,reqwest::Error>无法使用默认格式化程序格式化

python - 实例化类保留引用

java - 处理异常的方法包装?