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 特性的变量。

Rust 中的指针:Box、Rc、Cell、RefCell相关推荐

  1. Rust中Box、Rc、Arc、Cell、RefCell、Cow简介

    一.Box 是一种独享所有权智能指针,类似C++的unique_ptr 资源分配在堆上,依靠Deref和Drop来管理堆上的资源,零运行时开销,是最常用的套娃. Box::new(v): 创建,移动语 ...

  2. 怎么new一个指针_【译】Rust与智能指针

    原文链接:https://dev.to/imaculate3/that-s-so-rusty-smart-pointers-245l 原文标题:That's so Rusty!: Smart poin ...

  3. rust全息要啥才能做_在 Rust 中不能做什么

    编者注:上周 Armin 在自己的博客上首次发布了这个版本.如果你想再次阅读这篇文章,或者想看看 Armin 还在做什么,一定要去看看. 去年一直很有趣,因为我们用 Rust 建造了很多好东西,并且这 ...

  4. rust的矿坑_转: Rust中的Pin详解 【Rust语言中文社区】

    Rust中的Pin详解 原创 automanyang Rust语言中文社区 昨天 https://mp.weixin.qq.com/s/PjctbPbyR5OeaqTHZdB5uQ 相关概念 Pin ...

  5. c++ enum 给定类型_在 Rust 中创建 C/C++ API

    Rust 是一种神奇的语言,有着更好的生态系统.许多 Rust 的设计决策都非常适合向现有的C/C++系统添加新功能,或者逐步替换这些系统的部分! 当我尝试为 Rust 创建 C++ API 时,我发 ...

  6. i3够晚rust吗_【译】理解Rust中的Futures (一)

    原文标题:Understanding Futures In Rust -- Part 1 原文链接:https://www.viget.com/articles/understanding-futur ...

  7. 【Smart_Point】C/C++ 中智能指针

    C++11智能指针 目录 C++11智能指针 1.1 C++11智能指针介绍 1.2 为什么要使用智能指针 1.2.1 auto_ptr(C++98的方案,C++11已经抛弃)采用所有权模式. 1.2 ...

  8. 从内存布局上看,Rust的胖指针到底胖在栈上还是堆上?

    作者 | 马超       责编 | 张红月 出品 | CSDN 博客 2020 年转眼间白驹过隙般飞奔而去,在岁末年初的当口,笔者在回顾这一年程序员世界的大事件后,突然发觉如何避免程序员面向监狱编程 ...

  9. rust中的slice

    一.什么是切片(Slice) 切片这个概念很形象,也很容易为人理解.正如一个面包,如果一个无法吃掉全部,那么给他切一片不正好么?既不浪费,又不会引起不必要的后果.这样比喻不是很贴切,但其实意思有些类似 ...

最新文章

  1. 数字断路器获得商用认证
  2. Ashby diagram
  3. 微信小程序没登录跳到登录页怎么做_微信小程序手机端如何实现登录页面跳转含有Tabar页面...
  4. 目标检测综述——单阶段检测器
  5. java开发微信提现_java 微信提现至零钱
  6. 中南大学07 MATLAB中字符串的处理
  7. SQL Server 中的例程分析
  8. 2021年8月21日 Python图像全景拼接
  9. 在取证过程中,常见的一些注册表键值整理
  10. 计算机论文目录大全,毕业论文目录范文
  11. Eclipse:source 1.5 中不支持 diamond 运算符
  12. 电子邮箱免费注册,比较好用的电子邮箱怎么注册?如何申请?
  13. OSChina 周三乱弹 ——我们IT工程师会缺女友?
  14. 前端web实训——小米商城(第一天)
  15. 张益唐被曝已证明黎曼猜想相关问题,震动数学界
  16. php版工行聚合支付和e支付
  17. mysql攻城掠地_攻城掠地单机武将修改造出自己心目中大神.doc
  18. 盲孔、埋孔、通孔、一阶HDI、二阶HDI概念
  19. 头脑王者服务器维护,微信头脑王者请求超时及查询服务器失败的解决方法
  20. word表格合并单元格后,光标居中

热门文章

  1. 25w年薪!这个行业好起来了!
  2. [转]Windows CE 6.0(PB6)离线安装版下载
  3. 让自己分享的网址在QQ中更有逼格
  4. 重选/重定向/盲重定向/切换的区别
  5. python 求 牛顿插值法中的差商表
  6. 太原理工大学计算机专业全国排名,2020计算机专业大学排名
  7. mybatis的association以及collection的用法
  8. FPGA设计经验之图像处理
  9. Monkey自动化测试
  10. 在SQL中修改数据库名称