参考和框之间的可变性差异

时间:2015-07-22 15:34:33

标签: pointers reference rust immutability

我正在尝试理解Rust指针类型及其与可变性的关系。具体来说,声明保存指针的变量的方式本身是可变的 - 即可以指向其他一些内存,并声明数据本身是可变的 - 即可以更改通过指针变量的值。

这就是我理解简单引用的方法:

let mut a = &5; // a is a mutable pointer to immutable data
let b = &mut 5; // b is an immutable pointer to mutable data

因此a可以更改为指向其他内容,而b则不能。但是,b指向的数据可以通过b更改,但不能通过a我能理解这一点吗?

对于问题的第二部分 - 为什么Box::new的行为似乎有所不同?这是我目前的理解:

let mut a = Box::new(5); // a is a mutable pointer to mutable data
let c = Box::new(7); // c is an immutable pointer to immutable data

new应该返回指向一些堆分配数据的指针,但它指向的数据似乎从保存指针的变量继承可变性,这与带有引用的示例不同,这两个可变性状态是独立! 这是Box::new应该如何工作的?如果是这样,我怎样才能在存储在不可变变量中的堆上​​创建可变数据的指针值?

1 个答案:

答案 0 :(得分:2)

首先,您了解引用的正确行为。 mut a是一个可变变量(或者更确切地说,是一个可变绑定),而&mut 5是一个可变引用,指向一个可变数据片段(在你的栈中隐式分配)。 / p>

其次,Box与引用的行为不同,因为它与引用的根本不同Box的另一个名称是拥有/拥有指针。每个Box 拥有它拥有的数据,并且唯一,因此该数据的可变性是从盒子本身的可变性继承的。是的,这正是Box应该如何运作的。

理解它的另一种可能更实际的方法是将Box<T>完全等同于T,除了固定大小和分配方法。换句话说,Box提供了值语义:它就像任何值一样被移动,它的可变性取决于它存储的绑定。

有几种方法可以在堆上创建指向可变数据的指针,同时保持指针不可变。最通用的是RefCell

use std::cell::RefCell;

struct X { id: u32 }
let x: Box<RefCell<X>> = Box::new(RefCell::new(X { id: 0 }));
x.borrow_mut().id = 1;

或者,您可以使用Cell(适用于Copy类型):

let x: Box<Cell<u32>> = Box::new(Cell::new(0));
x.set(1);

请注意,上述示例使用的是所谓的内部可变性&#34;除非你需要它,否则最好避免这种情况。如果你想创建一个带有可变内部的Box只是为了保持可变性,你真的不应该这样做。它不是惯用的,只会导致句法和语义上的负担。

您可以在此处找到许多有用的信息:

事实上,如果你对可变性等基本问题有疑问,可能已在书中解释过:)