我一直在学习Rust中的引用,发现很难理解引用是如何存储在堆栈中的。
考虑下面的程序:
fn main() {
let name = String::from("Somu");
let name_ref = &name;
}
现在,如何在堆栈帧中为这两个变量分配内存?
|--------------------|
| name | 0x1fcd |
|--------------------|
| name_ref | ? |
|--------------------|
因此,由于String存储在堆中,因此我们将字符串“Somu”所在的堆地址作为变量name
的值。
现在,name_ref
是对name
的引用。在Rust术语中,name_ref
借用了name
指向的值。
那么,堆栈帧中存储的get是什么,作为name_ref
的值?
- 包含字符串的堆内存的地址?
name
在堆栈中的地址?
还是别的什么?
有没有人能帮我补充一下这个概念?
先谢谢你了
3条答案
按热度按时间yrwegjxp1#
那么什么get作为name_ref的值存储在堆栈帧中呢?
堆栈中
name
的地址。引用是具有编译器在编译期间知道的一些附加属性的指针(可变性,别名,指向现有对象的保证,借用的生命周期等)。但最终它们只是引擎盖下的一个普通的旧指针。它们的大小为
usize
(wide/fat pointers除外)。并保存它们指向的对象的内存地址。您可以通过使用
{:p}
打印指针的地址来验证:这可以例如输出:
其中,前两个地址是堆栈变量
name
的地址,第三个地址是String
管理的堆分配的地址。b1payxdu2#
String
可以看作是一个有三个数据成员的结构体。当我们说一个
String
是堆分配的,它只是一个强调文本(utf-8字节序列)是堆分配的事实的捷径;结构体本身可能是堆栈分配的(取决于您的代码)。在您的示例中,
name
String
(结构体)是堆栈分配的,作为任何局部变量,尽管它包含的文本可能是堆分配的,并且name_ref
仅包含此结构体在堆栈上的地址(它指向堆栈上非常接近的地址)。请注意,这种描述代码功能的方式是对非优化编译器(如调试模式)功能的简化,其中每个变量都位于内存中并具有地址。当涉及到优化编译器时(如在发布模式下),许多变量并不简单地存在(在内存中有一个专用的存储),它们被重构为一系列对寄存器的等效操作和很少的内存访问。
6pp0gazn3#
它是对存储在堆栈上的
String
值的引用,这意味着该引用将存储指向该值的指针。引用将不引用堆;该分配在String
内部。然而,在编译器优化的情况下,很可能会省略这种引用。
同样值得注意的是,deref强制允许从
&String
创建&str
绑定,在这种情况下,&str
* 将 * 指向非空String
的堆。