如何理解由`as_ref()`和`as_ptr()`组成的链式调用中`&*`的结合性?

问题描述 投票:0回答:1

我正在阅读

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()) }
。他们是:

  1. &
    *
    总是具有最低优先级吗?也就是说,
    &*self.data.as_ref().unwrap().as_ptr())
    总是评估为
    &(*(self.data.as_ref().unwrap().as_ptr())))
    吗?
  2. &*
    似乎应该抵消,因此据说它们通常表示隐式
    deref()
    deref()
    发生在这里吗?如果是这样,它发生在哪里?如果不是,为什么将
    &*
    排除在外会导致
    mismatched types
    错误(“预期引用
    &T
    找到原始指针
    *mut T
    ”)?
  3. 与2相关。在
    *(self.data.as_ref().unwrap().as_ptr())
    中,将
    &Rc<RefCell<T>>
    (这是来自rust-analyzer的
    self.data.as_ref().unwrap()
    的类型提示)转换为原始指针
    *const RefCell<T>
    (我的理解,而不是rust-analyzer的)的目的是什么未能给出类型提示)然后
    *
    取消引用它?在最后一个最左边的
    &
    之前取消引用什么?
pointers rust reference dereference refcell
1个回答
0
投票
  1. 是的,

    &
    *
    具有相同的优先级,属于优先级最低的一元运算符。请参阅Rust 参考:表达式优先级

  2. 供参考,这通常是正确的。但就您而言,

    *
    是原始指针取消引用,这就是您需要
    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)

在这种情况下,

&*
用于从原始指针转换为引用。

  1. 让我们进一步拆分第一行:
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()
获得的引用无法逃逸函数体并被返回。
    

© www.soinside.com 2019 - 2024. All rights reserved.