首页
学习
活动
专区
圈层
工具
发布
    • 综合排序
    • 最热优先
    • 最新优先
    时间不限
  • 来自专栏学点Rust

    聊聊Rust的Cell和RefCell

    Cell和RefCell是Rust提供的两种内部可变性的实现。Cell是用于Copy类型的,而RefCell是用于非Copy类型的。 ("{}", s.into_inner()); RefCell 提供引用 RefCell主要的不同是支持非Copy类型,且返回的是引用,而不是值。 use std::cell::RefCell; let c = RefCell::new("hello".to_owned()); *c.borrow_mut() = "bonjour".to_owned RefCell 依旧要遵守借用规则,只是推迟检查从编译期到运行时,如果违反了借用规则,会 panic。 ```rust use std::cell::RefCell; let c = RefCell::new("hello".to_owned()); let val = c.borrow(); // 先借用再修改

    83630编辑于 2023-11-27
  • 来自专栏Rust语言学习交流

    【笔记分享】`Cell`与`RefCell`的关联与差别

    它们之间的不同点 上图的文字描述如下: 本质不同 Cell<T>“包含”的是【所有权】变量本身 RefCell<T>“包含”的是变量的【引用】。 即便RefCell::new(...)构造函数的实参是【所有权】变量,这也不影响其内部重点使用该变量的【内存地址】。 <T>违背【借入规则】的代码会导致【编译失败】 RefCell<T>违背【借入规则】的代码会导致【运行时-程序崩溃panic】 计算成本 Cell<T>编译时成本 RefCell<T>运行时成本 读取【 <T>就三步: 通过【运行时-借入检查器】的审查 RefCell<T>::borrow()取出变量的内存地址 *RefCell<T>::borrow()以【去引用-操作符】取出该地址位置上被保存的值。 -借入检查器】的审查 RefCell<T>::borrow_mut()取出变量的内存地址 *RefCell<T>::borrow_mut()以【去引用-操作符】修改该地址位置上被保存的值。

    60110编辑于 2022-03-28
  • 来自专栏福大大架构师每日一题

    2022-05-22:给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。

    代码如下: use std::cell::RefCell; use std::rc::Rc; fn main() { let mut head = Rc::new(RefCell::new(Some <Option<TreeNode>>>, mut o1: Rc<RefCell<Option<TreeNode>>>, mut o2: Rc<RefCell<Option<TreeNode (RefCell::new(None)); let mut ans: Rc<RefCell<Option<TreeNode>>> = Rc::new(RefCell::new(None)); > = Rc::new(RefCell::new(None)); let mut next: Rc<RefCell<Option<TreeNode>>> = Rc::new(RefCell::new : Rc<RefCell<Option<TreeNode>>> = Rc::new(RefCell::new(None)); let mut first: Rc<RefCell<Option<TreeNode

    58410编辑于 2022-05-22
  • 来自专栏CSDNToQQCode

    Rust专项——智能指针与内在可变性详解(Box/Rc/Arc/Cell/RefCell/Mutex/RwLock)

    Cell 与 RefCell:内在可变性(单线程) Cell<T>:按值替换(Copy 友好),提供 get/set/replace; RefCell<T>:运行时借用检查,提供 borrow()/borrow_mut use std::cell::RefCell; struct Counter { inner: RefCell<i32> } impl Counter { fn inc(&self) { *self.inner.borrow_mut 组合:Rc<RefCell> 与 Arc<Mutex> 单线程共享 + 可变:Rc<RefCell<T>>; 多线程共享 + 可变:Arc<Mutex<T>> / Arc<RwLock<T>>。 use std::cell::RefCell; use std::rc::Rc; #[derive(Debug)] struct Node { val: i32, next: Option<Rc<RefCell { val: i32, parent: RefCell<Weak<Node>>, children: RefCell<Vec<Rc<Node>>> } Weak<T> 不增加强计数,升级时用 upgrade

    25810编辑于 2025-12-16
  • 来自专栏繁依Fanyi 的专栏

    【Rust 基础篇】Rust 的 `Rc<RefCell<T>>` - 共享可变性的智能指针

    Rc<RefCell<T>> 的定义和特性 Rc<RefCell<T>> 是一个由两部分组成的智能指针: Rc 是一个引用计数指针,它允许多个所有者共享相同的数据。 RefCell 是一个在有多个引用的情况下允许对数据进行可变操作的容器。 Rc<RefCell<T>> 的使用 下面是一个示例,演示了 Rc<RefCell<T>> 的使用方法: use std::rc::Rc; use std::cell::RefCell; struct Rc<RefCell<T>> 的应用场景 Rc<RefCell<T>> 在多线程编程和递归数据结构中是非常有用的。 在多线程编程中,我们可以使用 Rc<RefCell<T>> 来实现多个线程之间共享可变数据。而在递归数据结构中,Rc<RefCell<T>> 可以用来构建相互引用的节点。

    1.4K30编辑于 2023-10-12
  • 来自专栏福大大架构师每日一题

    2022-05-22:给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。

    代码如下: use std::cell::RefCell; use std::rc::Rc; fn main() { let mut head = Rc::new(RefCell::new(Some <Option<TreeNode>>>, mut o1: Rc<RefCell<Option<TreeNode>>>, mut o2: Rc<RefCell<Option<TreeNode (RefCell::new(None)); let mut ans: Rc<RefCell<Option<TreeNode>>> = Rc::new(RefCell::new(None)); > = Rc::new(RefCell::new(None)); let mut next: Rc<RefCell<Option<TreeNode>>> = Rc::new(RefCell::new : Rc<RefCell<Option<TreeNode>>> = Rc::new(RefCell::new(None)); let mut first: Rc<RefCell<Option<TreeNode

    55720编辑于 2022-06-04
  • 来自专栏福大大架构师每日一题

    2022-05-22:给定一个二叉树,找到最近公共祖先。rust代码修改

    rust代码修改如下: use std::cell::RefCell; use std::rc::Rc; fn main() { let mut head = Some(Rc::new(RefCell <TreeNode>>>, mut o1: Option<Rc<RefCell<TreeNode>>>, mut o2: Option<Rc<RefCell<TreeNode >>>, ) -> Option<Rc<RefCell<TreeNode>>> { // if (findFirst(o1.left, o1, o2) ! <RefCell<TreeNode>>> = None; //TreeNode next = null; let mut next: Option<Rc<RefCell<TreeNode <TreeNode>>>, mut o1: Option<Rc<RefCell<TreeNode>>>, mut o2: Option<Rc<RefCell<TreeNode>>>, )

    42620编辑于 2022-05-23
  • 来自专栏码上读书

    Rust学习笔记Day15 标记trait有哪些常用trait

    也就是说,任何使用了 Cell 或者 RefCell 的数据结构不支持 Sync。 引用计数 Rc 不支持 Send 也不支持 Sync。所以 Rc 无法跨线程。 那RefCell可以吗? 我们也来试一下: std::{ cell::RefCell, thread, }; fn refcell_is_send() { let a = RefCell::new(1) 继续尝试 use std::{ cell::RefCell, sync::Arc, thread, }; // RefCell 现在有多个 Arc 持有它,虽然 Arc 是 Send /Sync,但 RefCell 不是 Sync fn refcell_is_not_sync() { let a = Arc::new(RefCell::new(1)); let b =

    59220编辑于 2023-02-23
  • 来自专栏繁依Fanyi 的专栏

    【Rust 基础篇】Rust 引用循环:解析和避免

    use std::rc::{Rc, Weak}; use std::cell::RefCell; struct Node { data: i32, next: Option<Weak< RefCell<Node>>>, } fn main() { let node1 = Rc::new(RefCell::new(Node { data: 1, next: None, })); let node2 = Rc::new(RefCell::new(Node { data: 2, next: Some( ("Data: {}", node1_next_data); } } 在上述示例中,我们使用 Rc<RefCell<Node>> 替代了 Option<Box<Node>>,并使用 Rc::downgrade

    51320编辑于 2023-10-12
  • 来自专栏Rust语言学习交流

    【Rust每周一知】如何理解Rust中的可变与不可变?

    Cell和RefCell std::cell模块中的Cell<T>和RefCell<T>是两个提供内部可变性的共享可变容器。 示例如下: use std::cell::RefCell; use std::thread; let result = thread::spawn(move || { let c = RefCell (result.is_err()); use std::cell::RefCell; fn main() { let c = RefCell::new(5); *c.borrow_mut , x.borrow()); } Cell<T>和RefCell<T>小结: Cell<T>适用于实现了Copy的类型(复制语义),RefCell<T>适用于未实现Copy的类型(移动语义)。 Cell<T>使用get/set方法操作值,RefCell<T>使用borrow/borrow_mut方法获取引用进而再操作值。

    2.3K20发布于 2019-12-25
  • 来自专栏云微的一点分享

    rust 入门笔记:使用rust实现双向链表、二叉树

    数据结构定义: use std::rc::Rc; use std::cell::RefCell; use std::clone::Clone; #[derive(Debug)] struct ListNode { value :i32, next: Option<Rc<RefCell<ListNode>>>, prev: Option<Rc<RefCell<ListNode>>> } #[derive(Debug)] pub struct List{ count: i32, first: Option<Rc<RefCell<ListNode>>>, last : Option<Rc<RefCell<ListNode>>> } 函数实现 impl ListNode { fn new(value:i32) -> Rc<RefCell<ListNode>> RefCell<TreeNode>>> } 函数实现 impl TreeNode { fn new(key:i32,value:String) -> Rc<RefCell<TreeNode>>{

    81020编辑于 2023-02-11
  • 来自专栏Rust语言学习交流

    【译】Rust与智能指针

    借用规则仍然适用,因此,如果在同一个作用域中使用了多个 RefCell<T>,程序将在运行时发生 panic。 因此,prev和next字段的类型就变成了 Rc<RefCell<Option<DoubleNode>>>。 : Rc<RefCell<Option<DoubleNode>>>, prev: Rc<RefCell<Option<DoubleNode>>>, } fn main() { let new(RefCell::new(None)), }; let a = Rc::new(RefCell::new(Some(node_a))); let node_b = DoubleNode next: Rc<RefCell<Option<DoubleNode>>>, prev: Weak<RefCell<Option<DoubleNode>>>, } fn main() {

    1.5K21发布于 2020-10-26
  • 来自专栏Rust语言学习交流

    【Rust精彩blog】Rust 中几个智能指针的异同与使用场景

    相对于标准情况的静态借用,RefCell<T> 实现了运行时借用,这个借用是临时的,而且 Rust 的 Runtime 也会随时紧盯 RefCell<T> 的借用行为:同时只能有一个可变借用存在,否则直接 use std::cell::RefCell; use std::thread; fn main() { thread::spawn(move || { let c = RefCell 可以看到各个智能指针可以解决其中一个问题,既然如此,为何我们不把 Rc<T> 与 RefCell<T> 组合起来使用呢? use std::rc::Rc; use std::cell::RefCell; fn main() { let shared_vec: Rc<RefCell<_>> = Rc::new(RefCell , shared_vec.borrow()); } 通过 Rc<T> 保证了多所有权,而通过 RefCell<T> 则保证了内部数据的可变性。

    2.1K20发布于 2020-02-20
  • 来自专栏学点Rust

    聊聊共享所有权之Rc和Arc

    当然,如果想保持值修改的同步,可以使用之前提到的Cell和RefCell,这两个类型可以实现内部可变性,可以在不可变引用的情况下修改值。 use std::{rc::Rc, cell::RefCell}; struct Owner { name: String, gadgets: RefCell<Vec<Rc<Gadget use std::rc::Rc; use std::rc::Weak; use std::cell::RefCell; struct Owner { name: String, gadgets : RefCell<Vec<Weak<Gadget>>> } struct Gadget { id: i32, owner: Rc<Owner> } fn main() { 推荐阅读 掌握Rust:从零开始的所有权之旅 聊聊Rust的Cell和RefCell 如果有用,点个 在看 ,让更多人看到 外链不能跳转,戳 阅读原文 查看参考资料

    61120编辑于 2023-11-27
  • 来自专栏福大大架构师每日一题

    2022-10-09:我们给出了一个(轴对齐的)二维矩形列表 rectangles 。 对于 rectangle[i] = [x1, y1, x2, y2],其

    这道题用了树结构,对于rust有点复杂,用了Rc<RefCell<T>>的数据类型。力扣850上测试,rust语言占用内存最低,go语言占用内存略高于rust,但运行速度最快。 代码如下:use std::cell::RefCell;use std::iter::repeat;use std::rc::Rc;impl Solution { pub fn rectangle_area usize][3]); } return ans as i32;}struct Node { cover: i64, len: i64, left: Option<Rc<RefCell <Node>>>, right: Option<Rc<RefCell<Node>>>,}impl Node { fn new() -> Self { Self { Option::None, right: Option::None, } }}struct DynamicSegmentTree { root: Rc<RefCell

    47810编辑于 2022-10-09
  • 来自专栏每月技术成长

    2023学习日志

    RefCell<T>运行时检查借用规则RerCell<T>遵循内部可变性模式,在运行时检查借用规则而非编译时。 因为RefCell<T>允许在运行时检查借用规则,因此可以在RefCell自身不可变的情况修改其内部的值。 示例: use std::cell::RefCell; trait Messenger { fn send(&self, msg: &str); } struct <T>智能指针,每次调用borrow方法,RefCell<T>将不可变借用计数加一,当Ref<T>指针离开作用域时,不可变计数减一。 与编译时借用规则相同:RefCell<T>在任何时刻只允许存在多个不可变借用或一个可变借用。

    44710编辑于 2023-07-27
  • 来自专栏福大大架构师每日一题

    2023-05-10:给你一棵以 root 为根的二叉树和一个 head 为第一个节点的链表 如果在二叉树中,存在一条一直向下的路径 且每个点的数值恰好一一对应

    : nil,},},}res := isSubPath(head, root)fmt.Println(res) // output: true}图片rust完整代码如下:use std::cell::RefCell #[derive(Debug, PartialEq, Eq)]pub struct TreeNode { pub val: i32, pub left: Option<Rc<RefCell< TreeNode>>>, pub right: Option<Rc<RefCell<TreeNode>>>,}impl TreeNode { #[inline] pub fn new( left: None, right: Some(Rc::new(RefCell::new(TreeNode { val: 2, ::new(TreeNode { val: 4, left: Some(Rc::new(RefCell::new(TreeNode {

    56300编辑于 2023-05-10
  • 来自专栏码上读书

    Rust编程学习笔记Day7-一个值可以有多个所有者吗?

    到目前为止,只有Rc和接下来将学到的RefCell,Cell,Arc用到了动态检查,旗鱼都是静态检查。注意:动态检查仍然会校验所有权规则。 RefCell Rc只是一个只读引用计数器,我们没有办法拿到Rc结构的内部数据的可变引用,来修改这个数据,因此需要RefCell来达成对只读数据的可变借用,称为内部可变性,Rc和RefCell可以搭配使用 也就是说在编译器眼里,这个值它是只读的,但是到运行时,这个值它是可以得到可变借用,修改其内部数据,这就是RefCell的用武之地。 上代码: use std::cell::RefCell; fn main() { let data = RefCell::new(1); { // 获得 RefCell , data.borrow()); } 这一坨代码里,data并没有用mut 来声明,只是一个RefCell,但是在后面却可以用borrow_mut获得一个可变借用,把data里的值+1了。

    1.4K30编辑于 2023-02-23
  • 来自专栏Rust语言学习交流

    【Rust每周一知】如何理解Rust的默认线程安全?

    本文以Rc和RefCell为例,讨论Rust中的Send和Sync是如何保证线程安全的。 基本概念 Send和Sync位于标准库std::marker模块中。 Rc和RefCell示例 线程间传递可变字符串。 Rc表示“Reference Counted”(引用计数),单线程引用计数指针。 RefCell表示可变的内存位置,运行时检查借用规则。 ; }); } } 编译再次报错,错误信息告诉我们,std::cell::RefCell<std::string::String>无法在线程之间安全地共享。 这是因为RefCell<String>没有实现Sync。

    1.7K10发布于 2020-02-12
  • 来自专栏繁依Fanyi 的专栏

    【Rust 基础篇】Rust 弱引用:解决引用循环与内存泄漏

    use std::rc::{Rc, Weak}; use std::cell::RefCell; struct Node { data: i32, next: Option<Weak< RefCell<Node>>>, } fn main() { let node1 = Rc::new(RefCell::new(Node { data: 1, next: None, })); let node2 = Rc::new(RefCell::new(Node { data: 2, next: Some( // node1 弱引用了 node2 node1.borrow_mut().next = Some(Rc::downgrade(&node2)); } 在上述示例中,我们使用 Rc<RefCell

    75820编辑于 2023-10-12
领券