在Rust中,指向自身的引用是如何工作的?

g6baxovj  于 2023-08-05  发布在  其他
关注(0)|答案(1)|浏览(109)

我正在尝试学习Rust。我看到它可以对自己的地址(下面的y = &y)进行引用,然而,由于某种原因,程序仍然能够找到引用最初指向的内容;

let x = 1;
let mut y = &x;
println!("{y:p} -> {y}"); // 0x7fffb13d6f6c -> 1
y = &y;
println!("{y:p} -> {y}"); // 0x7fffb13d6f6c -> 1

字符串
我所理解的是,在第二行之后,记忆看起来像下面这样;
| 地址|价值| value |
| --|--| ------------ |
| a1|一个| 1 |
| A2| a1| a1 |
如果指令y = &y把内存变成这样;
| 地址|价值| value |
| --|--| ------------ |
| a1|一个| 1 |
| A2| A2| a2 |
println!将能够输出它在最后一行上输出的内容,那么第四行到底做了什么,它之后的内存是什么样子的呢?

yhuiod9q

yhuiod9q1#

y不指向自身。这是不可能的。y正好指向它之前指向的位置,而赋值y = &y什么也不做。
那么,它的含义是什么?为什么要编译?
要回答这个问题,我们需要看看类型。这里有一个神秘的东西:如果y的类型为&i32,那么&y的类型为&&i32,那么,当&yy的类型完全不同时,您如何将它们赋值给它们呢?
答案是deref强制。在编写y = &y时,编译器会尝试匹配类型。它无法将&&i32&i32进行匹配,但它会尝试提供帮助,并认为:“很可能,程序员有一些引用,他想取消引用,但只是没有明确地写出来。所以我会为他这么做!“例如,这对于将&String传递给采用&str的函数非常有用。&String&str的类型不同,但String引用了str,因此我们可以将其转换为&**s,首先从&String创建String,然后从该String创建str,最后引用该String创建&str
因此,y = &y等价于y = &*y。它只接受一个引用,然后立即取消引用,也就是说,只将y中的值再次复制到y中,有效地保留了它。

相关问题