我正在阅读
linkedlist
,这是一个如何为 Brenden Matthews 的书 Idiomatic Rust(第 6 章)中的链表实现 Iterator
的示例。完整的代码可以从同一网站 (ch06/linkedlist/src/lib.rs
) 的源代码访问。以下是摘录的片段,以显示我的困惑。
type ItemData<T> = Rc<RefCell<T>>;
type ListItemPtr<T> = Rc<RefCell<ListItem<T>>>;
struct ListItem<T> {
data: ItemData<T>,
next: Option<ListItemPtr<T>>,
}
pub struct LinkedList<T> {
head: Option<ListItemPtr<T>>,
}
impl<T> LinkedList<T> {
pub fn new() -> Self {
... // code omitted
}
pub fn append(&mut self, t: T) {
... // code omitted
}
pub fn iter(&self) -> Iter<T> {
Iter {
next: self.head.clone(),
data: None,
phantom: PhantomData,
}
}
}
pub struct Iter<'a, T> {
next: Option<ListItemPtr<T>>,
data: Option<ItemData<T>>,
phantom: PhantomData<&'a T>,
}
impl<'a, T> Iterator for Iter<'a, T> {
type Item = &'a T;
fn next(&mut self) -> Option<Self::Item> {
match self.next.clone() {
Some(ptr) => {
self.next = ptr.as_ref().borrow().next.clone();
self.data = Some(ptr.as_ref().borrow().data.clone());
unsafe { Some(&*self.data.as_ref().unwrap().as_ptr()) }
}
None => None,
}
}
}
我的问题都是关于最后一部分的
unsafe { Some(&*self.data.as_ref().unwrap().as_ptr()) }
。他们是:
&
和*
总是具有最低优先级吗?也就是说,&*self.data.as_ref().unwrap().as_ptr())
总是评估为&(*(self.data.as_ref().unwrap().as_ptr())))
吗?&*
似乎应该抵消,因此据说它们通常表示隐式 deref()
。 deref()
发生在这里吗?如果是这样,它发生在哪里?如果不是,为什么将 &*
排除在外会导致 mismatched types
错误(“预期引用 &T
找到原始指针 *mut T
”)?*(self.data.as_ref().unwrap().as_ptr())
中,将&Rc<RefCell<T>>
(这是来自rust-analyzer的self.data.as_ref().unwrap()
的类型提示)转换为原始指针*const RefCell<T>
(我的理解,而不是rust-analyzer的)的目的是什么未能给出类型提示)然后 *
取消引用它?在最后一个最左边的&
之前取消引用什么?是的,
&
和*
具有相同的优先级,属于优先级最低的一元运算符。请参阅Rust 参考:表达式优先级
供参考,这通常是正确的。但就您而言,
*
是原始指针取消引用,这就是您需要 unsafe
的原因。这是这个表达式,分开后:
let data_ptr: *mut T = self.data.as_ref().unwrap().as_ptr();
let data_reref: &T = &( // Taking a reference to that "place"
unsafe { *data_ptr } // Dereferencing the raw pointer to the "place"
);
Some(data_reref)
在这种情况下,
&*
用于从原始指针转换为引用。
let data_ref: &Rc<RefCell<T>> = self.data.as_ref().unwrap(); // Option::as_ref, Option::unwrap
let data_ptr: *mut T = data_ref.as_ptr(); // RefCell::as_ptr
as_ptr
此处解析为RefCell::as_ptr
,因为Rc::as_ptr
无法被方法调用。它只能像 Rc::as_ptr(an_rc)
那样调用,因为它不需要 self
参数。 RefCell::as_ptr
为我们提供了指向 RefCell
中保存的数据的原始指针。
这是必要的,因为从
.borrow()
获得的引用无法逃逸函数体并被返回。