【问题标题】: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 会推断出正确的返回类型,同时确保借用检查器可变借用是安全的。