在Rust中解除Rc <Vec <T >>的混淆

sou*_*ics 5 dereference rust

为什么以下代码有效?

use std::rc::Rc;
fn main () {
    let c = vec![1, 2, 3, 4, 5];
    let r = Rc::new(c);
    println!("{:?}", (**r)[0]);
}
Run Code Online (Sandbox Code Playgroud)

我可以理解它与单个deference(println!("{:?}", (*r)[0]);)一起工作.但是也无法理解它与双重引用一起工作.

Tim*_*ann 10

这两种,RCVEC实现DEREF,伟驰deref-方法时调用*.

let c = vec![1, 2, 3, 4, 5];
Run Code Online (Sandbox Code Playgroud)

创建一个VEC与和所述给定元素vec!-macro.

let r = Rc::new(c);
Run Code Online (Sandbox Code Playgroud)

从Vector 创建一个引用计数对象.Vector被移入RC.

println!("{:?}", (**r)[0]);
Run Code Online (Sandbox Code Playgroud)

这个有点棘手:*r 取消引用 Rc,所以我们得到了底层的Vector.将Vector *rc 取消引用作为切片.slice[0] 索引切片的第一个元素,这将导致第一个元素1.println!最后打印结果.


E_n*_*ate 7

一旦我们围绕表达式构建函数原型,可能更容易理解会发生什么(**r)[0]:

fn foo<T, U>(r: T) -> i32
where
    T: Deref<Target=U>,
    U: Deref<Target=[i32]>,
{
    (**r)[0]
}
Run Code Online (Sandbox Code Playgroud)

操场

Rc<T>,就像Rust中大多数智能容器的典型情况一样Deref,它实现了它可以用作对底层值的普通引用.反过来,Vec<T>实现,Deref以便它可以用作slice(Target = [T]).显式解除引用*,执行两次时,按顺序应用两次转换.

当然,通常你不需要这样做,因为它Vec也实现了Index操作符.