摘要:Rust 内部可变性概念:
UnsafeCell/Cell/RefCell 概念,用法及内部机制
*引言
fn main() {
// let x = 1;
let mut x = 1;
x += 1;
println!("The value of x is {}.", x);
}
// 如果我想更新函数中的变量,但又不想传递所有权时---使用一个可变的引用
fn add_and_print(x: &mut i32) {
*x += 1;
println!("The value of x in add_and_print is {}.", x); // 2
// 引用继承了直接从当前作用域向下传递的可变性---与下面要说的内部可变性相反
}
fn main() {
let mut x = 1;
add_and_print(&mut x);
x += 1;
println!("The value of x in main is {}.", x); // 3
}
// 包含对 i32 的可变引用的结构,因此所有权不会改变
struct XStruct<'a> {
x: &'a mut i32,
}
fn main() {
let mut x = 1;
let x_struct = XStruct {
x: &mut x };
// x += 1; // Modify x... 不能这么做
println!("The value of x_struct is {:?}.", x_struct); // 1
println!("The value of x is {:?}.", x); // 1
}
// 为什么不能这么做? 回顾一下 Rust 的借用规则:
// 可以有一个可变引用
// 可以有多个不可变引用
// 引用总是有效的
// 在这个例子中 我们有两个对 的引用,我们希望这些引用是可变的。
//(是的,我知道,不是借来的,拥有它的价值,但我仍然认为它能够改变它自己的数据)
// 与借用规则相驳,原因是为了防止数据竞争,这可能导致一些非确定性错误---不展开讲述
// 基于这些规则,我想要多个可变的引用---内部可变性
// 内部可变性是Rust的设计模式之一
// 它允许我在只持有不可变引用的前提下对数据进行修改---类似的行为会被借用规则所禁止
// 但是为了改变数据,内部可变性在它的数据结构里面使用了unsafe代码来绕过Rust正常的可变性和借用规则---先不细说,继续往下看
// 实现内部可变性的方式---UnsafeCell、Cell、ReCell
一、内部可变性简介
内部可变性,有时候也叫共享可变性,就是说它持有共享引用又可以改变数据。
让程序拥有多个共享引用的时候还可以修改引用的数据。比如对外看起来是不变的接口,内部仍然有改变。
二、UnsafeCell 基本用法及内部机制
有一个get方法,通过不可变引用(&T),获取到了可变裸指针 (*mut T),它是通过强转来实现的
pub const fn get(&self) -> *mut T {
self as *const UnsafeCell<T> as *