从https://www.reddit.com/r/rust/comments/3geb5q/learning_rust_with_entirely_too_many_linked_lists/ctxgwmz ,也许可以解释&**node
以使其更明显地被取消引用。 来自C,这有点令人困惑。
感谢您记录问题:+1:
只是偶然发现了这一点,我什**
在3.5 iter中的第 369 行(或在“(ノಥ益ಥ)ノ ┻━┻ ”之后) 中发现新的**
并且非常惊讶在最终代码中看到它。
我也没有完全理解我们需要as_ref()
是不是太明显
我正在浏览本节,第 259 行的&**node
应该是&*node
吗? 我可能漏掉了一些东西,但我没有看到它从上一节改变的理由。
https://github.com/Gankro/too-many-lists/blame/master/text/second-iter.md#L259
第 123123 行错误中的类似问题。
https://github.com/Gankro/too-many-lists/blame/master/text/second-iter.md#L123
记住我们在Iter::next
想要的是Option<&Node<T>>
, &
是引用,而*
是取消引用,就像在 C 中一样。
self.head
是Option<Box<Node<T>>>
所以没有as_ref()
, map()
node
是Box<Node<T>>
。 一种取消引用, *
,摆脱Box<>
并取出Node<T>
。 然后我们用&
引用它。
但是,随着as_ref()
返回Option<&Box<Node<T>>>
,在map()
node
变成了&Box<Node<T>>
。 &
一个取消引用和Box<>
另一个取消引用,需要两次取消引用才能取出Node<T>
。 然后用&
引用它。
@马克威克
恕我直言,主题是我们不能简单地将结果移出Option<>
。 我们要么使用take()
或map()
它,要么使用as_ref()
查看它。 如果我们将它与map()
但只返回一个引用,则一旦返回引用,节点本身就会超出范围。 所以我们必须首先查看它as_ref()
,然后map()
引用出来以取消引用节点。
为了与本书的主题保持一致,在添加as_ref
然后修复它并解释原因之后,该部分可能会有另一个编译器因类型不匹配而向我们尖叫的情况。 此外,在需要进行更改之前,文本中有几个部分会剧透并显示**
。
在查看“官方”解决方案之前,我仍在阅读本书,并始终尝试自己实现当前功能(例如.iter()
)(仅使用 Rust 文档)。 我的iter()
最终看起来有点不同:
pub struct List<T> {
head: Link<T>,
}
type Link<T> = Option<Box<Node<T>>>;
struct Node<T> {
elem: T,
next: Link<T>,
}
impl<T> List<T> {
// [...]
pub fn iter(&self) -> Iter<T> {
Iter(&self.head)
}
}
pub struct Iter<'a, T: 'a>(&'a Link<T>);
impl<'a, T> Iterator for Iter<'a, T> {
type Item = &'a T;
fn next(&mut self) -> Option<Self::Item> {
self.0.as_ref().map(|node| {
self.0 = &node.next;
&node.elem
})
}
}
不知道这是任何更好或更坏,但它摆脱两者的&**
还有.map()
呼叫List::iter()
,这感觉就像代码的重复在Iter::next()
给我。
编辑:不幸的是,我正在努力为iter_mut()
使用相同的方法:(
使用.map(Box::deref)
而不是.map(|node| &**node)
可能更清楚。
我刚刚发布了一个重大更新,修复此问题是其中一项更改。
(虽然使用 Box::deref 很有趣)
我在操场上尝试了@m-ou-se 的建议: https : =7156f8fdd1d3c883379b5de868f230be
好奇,我去阅读Box::deref
的
impl<T: ?Sized> Deref for Box<T> {
type Target = T;
fn deref(&self) -> &T {
&**self
}
}
我相信这可以与take()
和map()
。
顺便说一句,更通用的Deref::deref
也有效。
嗨,我今天正在学习教程,偶然发现了这一章……我的解决方案如下:
Iter { next: self.head.as_ref().map(|boxed_node| boxed_node.as_ref()) }
我不知道人们是否通常通过*
&
手动取消引用*
但为此目的添加另一个*
似乎有些不自然,最重要的是,生成的代码看起来并不对我来说很容易理解。
其实我也只是继续阅读Box.as_ref()
的
#[stable(since = "1.5.0", feature = "smart_ptr_as_ref")]
impl<T: ?Sized> AsRef<T> for Box<T> {
fn as_ref(&self) -> &T {
&**self
}
}
我认为Box::deref
和Box.as_ref
都应该优先于教程中的当前解决方案
最有用的评论
我在操场上尝试了@m-ou-se 的建议: https : =7156f8fdd1d3c883379b5de868f230be
好奇,我去阅读
Box::deref
的我相信这可以与
take()
和map()
。顺便说一句,更通用的
Deref::deref
也有效。