【问题标题】:Simple as possible example of returning a mutable reference from your own iterator从您自己的迭代器返回可变引用的尽可能简单的示例
【发布时间】:2015-01-22 23:10:38
【问题描述】:

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

我的问题是:

在设计您的自己的迭代器时可以采取哪些具体步骤,以便它可以产生可变引用?最终,我希望有一个简洁的、逐步的、注释过的Iterator 及其next 实现的示例,我(和任何人)可以在它们运行时作为明确的参考陷入这种境地。 unsafe 例子很好,我想它们可能是必要的!

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

【问题讨论】:

标签: reference iterator rust mutable lifetime


【解决方案1】:

这是一种在假设的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);
}

另见

【讨论】:

  • 谢谢!我最终在自己的用例中做到了这一点。对于任何不确定 transmute 做什么的人,这里是其行为的摘要 from the docs,“不安全地将一种类型的值转换为另一种类型的值。”在这种情况下,transmute 会推断出正确的返回类型,同时确保借用检查器可变借用是安全的。
猜你喜欢
  • 1970-01-01
  • 2018-05-31
  • 2019-01-12
  • 2018-11-15
  • 2015-07-23
  • 2017-03-20
相关资源
最近更新 更多