在 Rust 中,引用一个 int 类型的盒子和引用一个 int 类型有什么区别?

3

最近我开始学习Rust编程并需要帮助。这是我的代码,它应该接受一个指向堆分配的整数的引用,并改变它的值。

let mut boxed_int = box 5;
let _ref_to_int   = &mut *boxed_int;   // why it is &int ???
*_ref_to_int      = 10;

let mut boxed_int = box 5;
let _ref_to_int   = &mut boxed_int;
*_ref_to_int      = box 10;

最后一行代码是否会删除堆上的5并在同一地址分配10呢?还是5没有被删除,现在指针指向堆上另一个地址,并且该地址的值为10?

1个回答

4

以下是带有显式类型标注的程序:

let mut boxed_int:   Box<int> = box 5;
let mut _ref_to_int: &mut int = &mut *boxed_int;      // (1)
*_ref_to_int = 10;

let mut boxed_int:   Box<int> = box 5;
let mut _ref_to_int: &mut Box<int> = &mut boxed_int;  // (2)
*_ref_to_int = box 10;

简单回顾一下:Box是一个智能指针,它封装了堆分配。它分配足够的空间来存储其包含类型的值,并跟踪此内存,在超出作用域时将其释放。基本上,这提供了类似值的语义。

在第一段代码中,您借用了boxed_int内容:首先,*Box<int>进行解引用,获取int,然后&mut立即创建一个引用,结果为&mut int。当然,*_ref_to_int = 10会覆盖盒子里的内容,因此此后boxed_int将包含10。这里不会发生任何分配或释放。

在第二段代码中,您借用了boxed_int本身,因此_ref_to_int的类型为&mut Box<int>*_ref_to_int = box 10然后替换盒装值本身。由于旧的盒装值立即超出范围,因此调用其析构函数,并释放相应的堆内存。然后在堆上分配了一块新的内存,并在刚刚释放的内存的位置写入指针(box 10)。

所以,

最后一行删除堆上的5并在同一地址分配了10吗?

是和不是。最后一行会删除堆上的5并分配10,但地址肯定不同。实际地址可能会不同,但您不会注意到它,因为Box不公开其数字值。


实际上并不是“自然”的过程。如果按照您所说的方式(解引用,然后创建可变引用),实际上会将包装的整数复制到堆栈中的新位置,并通过引用修改它。因此,Rust 在这里确实做了一些魔法。而 *_ref_to_int = 10 则会覆盖盒子内容。 - YoTengoUnLCD

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接