当前位置:网站首页>Rust 中的指针:Box、Rc、Cell、RefCell
Rust 中的指针:Box、Rc、Cell、RefCell
2022-04-23 05:45:00 【许野平】
Rust 中的指针:Box、Rc、Cell、RefCell
作者:许野平 2022-02-21
Rust 自身具有 &、* 操作符,可以实现变量引用和解引用。为什么又搞出这几个类型的指针呢?原因就是想突破 Rust 坚持的”共享不可写、可写不共享“的原则。我们看看 Rust 编译器的”道德底线“是如何被一步一步突破的吧。
1 Box 类型
我在《 Rust 的 Box指针》一文中详细讨论了 Box 的特点。看一个简单的例子:
fn main() {
let x = String::from("Hello!");
let y = Box::new(x);
println!("{:?}", y);
}
其实这段代码与下面的代码几乎是等价的:
fn main() {
let x = String::from("Hello!");
let y = &x;
println!("{:?}", y);
}
还有一段 Box 代码,展示了在设计链表结构时的用法:
#[derive (Debug)]
struct Node {
data: i32,
next: Option<Box<Node>>,
}
fn main() {
let x = Node {
data: 123,
next: None,
};
let y = Box::new(x);
println!("{:?}", y);
}
---------------------------------
>cargo run
Node {
data: 123, next: None }
我尝试把 Box 改成 &,结果因为生命周期的问题,我整了老半天也没能通过编译。代码贴到下面,哪位大神能给是点一下?
#[derive (Debug)]
struct Node <'a>{
data: i32,
next: Option<&'a Node>,
}
fn main() {
let x = Node {
data: 123,
next: None,
};
let y = Box::new(x);
println!("{:?}", y);
}
---------------------------------
>cargo run
--> src\main.rs:4:22
|
4 | next: Option<&'a Node>,
| ^^^^ expected named lifetime parameter
|
help: consider using the `'a` lifetime
别管 & 能不能代替 Box,反正这件事告诉我,Box 帮助我们简化了好多工作,比直接用 & 更省事。
2 Rc 类型
看下面的代码:
use std::rc::Rc;
fn main() {
let x = Rc::new(123);
let y = x.clone();
println!("{:?}, {:?}", x, y);
}
---------------------------------------------------
cargo run
123, 123
其实这个从逻辑上讲,也可以用 & 代替。一个变量的地址可以分配给多个变量,对不对?可是 rust 中的生命周期问题,够我们喝一壶的。所以,Rc 的存在价值就是可以避免生命周期检查,使得同一份数据可以在多个地方被引用。
3 Cell 类型
Cell 类型披着只读变量的外衣,允许程序修改变量内容。尽管 Rust 有一个原则——“共享不可写,可写不共享”,由于 Cell 表面上看是只读的,因此,Cell 类型的数据可以被多个地方引用,实现同一个数据可以被多个共享引用修改。因为 Cell 从语法上看是只读的,所以编译器不会报错。
Cell 可以用 get 方法返回数据。由于执行的 Copy 方法,因此要求数据必须实现 Copy 特性。
use std::cell::Cell;
fn main() {
let x = Cell::new(123);
x.set(456);
let y = x.get();
println!("{:?}, {:?}", x, y);
}
------------------------------------------------------
>cargo run
Cell {
value: 456 }, 456
4 RefCell
RefCell 与 Cell 基本相同,区别在于 RefCell 读取内容时,返回的是引用,本质上是一个指针。这是因为 RefCell 要包装的数据没有实现 Copy 特性。代码示例如下:
use std::cell::{
Ref, RefCell};
fn main() {
let x = RefCell::new("good".to_string());
let a = &x;
let b = &x;
*a.borrow_mut() = "nice".to_string();
*b.borrow_mut() = "best".to_string();
let y: Ref<String> = x.borrow();
println!("x = {:?}", x);
println!("y = {:?}", y);
}
---------------------------------------------------
>cargo run
x = RefCell {
value: "best" }
y = "best"
5 总结
- Box 等引用类型,简化了变量生命周期问题。
- Rc 允许 clone() 方法产生变量的多个副本,但这些副本并未真正分配内存,而是共享了相同的数据。
- Cell 在语法上看是只读的引用,而事实上是可以修改的。Cell 原则上只能引用实现了 Copy 特性的变量。
- RefCell 与 Cell 类似,但是可以引用未实现 Copy 特性的变量。
版权声明
本文为[许野平]所创,转载请带上原文链接,感谢
https://yeping.blog.csdn.net/article/details/123046750
边栏推荐
- Advanced operation of idea debug
- Kibana search syntax
- Solution to the trial of ycu Blue Bridge Cup programming competition in 2021
- Import of data
- MySQL table constraints and table design
- 線性代數第二章-矩陣及其運算
- 程序設計訓練
- Introduction to virtualization features
- MySQL best practices for creating tables
- -- SQL query and return limit rows
猜你喜欢
Substring Inversion (Easy Version)
How SYSTEMd uses / etc / init D script
Detection technology and principle
解决ArcGIS分区统计显示太多唯一值执行失败
[leetcode 202] happy number
Type conversion in C #
SQL sorts according to the specified content
SQL -- data filtering and grouping
St table template
[leetcode 19] delete the penultimate node of the linked list
随机推荐
POJ - 2955 brackets interval DP
Explanation of the second I interval of 2020 Niuke summer multi school training camp
A sharp tool to improve work efficiency
6.Reversal
C array
SQL -- data definition
Basic knowledge of network in cloud computing
Generate excel template (drop-down selection, multi-level linkage)
MySQL advanced query
卡尔曼滤波与惯性组合导航
[leetcode169] most elements
Rainbow (DP)
Sakura substring thinking
Definition of C class and method
Event listener
4. Print form
Algèbre linéaire chapitre 1 - déterminants
Doomsday (simple computational geometry)
[leetcode 350] intersection of two arrays II
Export of data