引用

那么引用,如 &String&mut String,它们在内存中是如何表示的呢?

Rust 中的大多数引用1在内存中都是以指向内存位置的指针形式表示的。因此,它们的大小与指针的大小相同,即 usize

你可以使用 std::mem::size_of 来验证这一点:

#![allow(unused)]
fn main() {
assert_eq!(std::mem::size_of::<&String>(), 8);
assert_eq!(std::mem::size_of::<&mut String>(), 8);
}

特别是,一个 &String 是指向存储 String 元数据的内存位置的指针。如果你运行这段代码:

#![allow(unused)]
fn main() {
let s = String::from("嘿");
let r = &s;
}

在内存中你会得到类似这样的布局:

           --------------------------------------
           |                                    |         
      +----v----+--------+----------+      +----|----+
Stack | pointer | length | capacity |      | pointer |
      |    |    |   3    |    5     |      |         |
      +----|----+--------+----------+      +---------+
           |        s                           r
           |       
           v       
       +---+---+---+---+---+
Heap   | H | e | y | ? | ? |
       +---+---+---+---+---+

可以说,这是一个指向指向堆分配数据的指针的指针。&mut String 的情况也是如此。

并非所有指针都指向堆

上述例子澄清了一点:并非所有指针都指向堆。它们只是指向一个内存位置,这个位置_可能_在堆上,但不一定是。

参考

  • 本节练习位于 exercises/03_ticket_v1/10_references_in_memory
1

在课程的后续部分中,我们将讨论胖指针,即带有附加元数据的指针。顾名思义,它们比本章讨论的指针(也称为瘦指针)更大。