Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >2023学习日志

2023学习日志

原创
作者头像
TomoriNao
发布于 2023-07-27 13:29:01
发布于 2023-07-27 13:29:01
1960
举报
文章被收录于专栏:每月技术成长每月技术成长

rust

智能指针

Box<T>指针

  • 堆上存储数据,而指针本身位于栈上 Box<T>类型的智能指针创建的是指向堆数据的指针,初始化过程中,会将数据分配在堆上,能够有效地节省栈上有限的空间,在所有权转移的过程中,复制的仅仅是一个栈上的指针,而非实际的数据,能够提高程序的性能 示例:
代码语言:rust
AI代码解释
复制
    fn main() {
        let b = Box::new(5);
        println!("b = {}",b);
    }
  • 允许创建递归类型 对于常见的cons list类型的数据结构(嵌套的列表),如果直接在声明结构体时进行嵌套,rust编译器无法推断出该类型数据占用的内存大小,会在编译时报错。 示例:
代码语言:rust
AI代码解释
复制
//编译时将报错,无法推断出List结构体的具体大小
    use crate::List::{Cons, Nil};
    enum List{
        Cons(i32,List),
        Nil,
    }
    fn main(){
        let list = Cons(1, Cons(2, Cons(3, Nil)));
    }

此时可以使用Box<T>指针指向嵌套的列表,得到cons list类型的结构体。(指针的内存大小是已知的,但列表的大小是在进行结构体声明时未知的)

示例:

代码语言:rust
AI代码解释
复制
// 此段代码不会报错,因为Box<T>为智能指针,大小固定,编译器可以推断出List类型的大小
    use crate::List::{Cons, Nil};
    enum List{
        Cons(i32, Box<List>),
        Nil
    }
    fn main(){
        let list = Cons(1, Box::new(Cons(2, Box::new(Cons(3, Box::new(Nil))))));
    }
  • 超出作用域之后,自动释放堆上数据 在超出作用域后,栈上的数据都会被逐一清除,而Box<T>智能指针在清除之前会调用其实现了的Drop trait的drop函数,清除所指向的堆上的数据。

Deref Trait 重载解引用运算符

智能指针类型的变量本身为指针类型,在使用时需要进行解引用来得到其所指向的数据。而解引用需要重载解引用运算符&。而通过实现Deref Trait,能够将类型像引用一样处理。

Deref trait需要实现其定义的deref方法,返回一个内部数据的引用

示例:

代码语言:rust
AI代码解释
复制
    //为Mybox<T>类型实现Deref trait
    use std::ops::Deref;
    impl<T> Deref for MyBox<T> {
        type Target = T;
        fn deref(&self) -> &self::Target {
            &self.0
        }
    }
    struct MyBox<T>(T);
    impl<T> MyBox<T> {
        fn new(x: T) -> MyBox<T> {
            MyBox(x)
        }
    }
    fn main() {
        let x=5;
        let y = MyBox::new(x);
        assert_eq!(5, x);
        assert_eq!(5, *y);
    }

Drop Trait 自动清除数据

Drop trait 类似于c++中的析构函数,在变量离开作用域时调用,清除数据或进行一些其他操作。

实现Drop trait需要实现其drop方法,该方法在变量离开时被调用,完成指定的一些操作。(主要目的为清理该变量拥有的数据)

此外,还可通过std::mem::drop 来在作用域结束前释放变量,std::mem::drop位于prelude中,因此无需显式引入该方法

示例:

代码语言:rust
AI代码解释
复制
    //为CustomSmartPointer结构体实现Drop trait
    struct CustomSmartPointer {
        data: String,
    }
    impl Drop for CustomSmartPointer {
        fn drop (&mut self){
            println!("Droping CustomSmartPointer with Data `{}`", self.data);
        
        }
    }
    fn main() {
        let c = CustomSmartPointer{
            data: String::from("my stuff"),
        };
        drop(c);
        let d = CustomSmartPointer{
            data: String::from("other stuff"),
        };
        println!("CustomSmartPointer created.");
    }

Rc<T>指针

Rc<T> 用于当我们希望在堆上分配一些数据供程序的多个部分读取,且无法在编译时确定程序的哪一部分会最终结束使用它的时候,如果确实知道哪部分是最后结束使用的话,可以令其成为数据的所有者,正常的所有权规则在编译时生效。

可以通过克隆Rc<T>的方式获取对堆上数据的引用,每次克隆时,引用计数增加1,当一个Rc<T>指针离开作用域时,引用计数减1,而当引用计数为0时,对应的drop方法将会被调用,堆上数据将会被清理。

注意:Rc<T>克隆的结果为不可变引用rust不允许同时存在多个可变引用

  • 强引用 --Rc<T> Rc<T>指针强引用,可以通过调用Rc::clone方法返回一个Rc<T>指针,会导致引用计数发生变化,当引用计数为0时,指针所指向的堆上数据将会被清理
  • 弱引用 --Weak<T> Weak<T>指针弱引用,可以通过Rc::downgrade方法返回一个*Weak<T>指针,不会导致引用计数发生变化,不会对堆上数据的清理产生影响 因为Weak<T>引用的值可能已经被丢弃了,因此需要在使用Weak<T>所指向的值时,调用Weak<T>实例的upgrade方法,返回一个Option<Rc<T>>

示例:

代码语言:rust
AI代码解释
复制
    use crate::List::{Cons, Nil};
    use std::rc::Rc;
    enum List {
        Cons(i32, Rc<List>),
        Nil,
    }
    fn main(){
        let a = Rc::new(Cons(5, Rc::new(Cons(10, Rc::new(Nil)))));
        println!("count after creating a = {}", Rc::strong_count(&a));
        //Rc::clone得到的是Rc<T>类型的强引用,会影响引用计数
        let b = Cons(3, Rc::clone(&a));
        println!("count after creating b =  {}", Rc::strong_count(&a));
        {
            let c = Cons(4, Rc::clone(&a));
            println!("count after creating c = {}", Rc::strong_count(&a));
        }
        println!("count after c goes out of scope = {}", Rc::strong_count(&a));
    }

RefCell<T>指针

  • 内部可变性 内部可变性rust中的一个设计模式,它允许你即使在有不可变引用时也可以改变数据,这通常是借用规则不允许的。该模式使用unsafe代码来模糊rust可变性借用规则。 当可以确保代码在运行时会遵守借用规则,即使是编译器无法保证的情况,可以选择使用运用了内部可变性模式的类型。
  • RefCell<T>运行时检查借用规则 RerCell<T>遵循内部可变性模式,在运行时检查借用规则而非编译时。 因为RefCell<T>允许在运行时检查借用规则,因此可以在RefCell自身不可变的情况修改其内部的值。 示例:
代码语言:rust
AI代码解释
复制
    use std::cell::RefCell;
    trait Messenger {
        fn send(&self, msg: &str);
    }
    struct MockMessenger {
        sent_messages: RefCell<Vec<String>>,
    }
    impl Messager for MockMessenger {
        fn send(&self, message: &str) {
            //borrow_mut()方法获取的是RefMut<T>类型的智能指针,borrow()方法获取的是Ref<T>类型的智能指针
            self.sent_message.borrow_mut().push(String::from(message));
        }
    }
  • RefCell<T>在运行时记录借用 borrow_mut方法获取的是RefMut<T>类型的智能指针,borrow方法获取的是Ref<T>类型的智能指针 RefCell<T>记录当前有多少个活动的Ref<T>RefMut<T>智能指针,每次调用borrow方法,RefCell<T>将不可变借用计数加一,当Ref<T>指针离开作用域时,不可变计数减一。可变借用计数规则类似不可解压计数规则。 与编译时借用规则相同:RefCell<T>在任何时刻只允许存在多个不可变借用一个可变借用。 示例:
代码语言:rust
AI代码解释
复制
    impl Messenger for MockMessenger {
        fn send(&self, message: &str){
            //代码将报错,不能同时存在两个可变借用
            let mut one_borrow = self.sent_message.borrow_mut();
            let mut two_borrow = self.sent_message.borrow_mut();
        }
    }

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
rust智能指针
智能指针虽然也号称指针,但是它是一个复杂的家伙:通过比引用更复杂的数据结构,包含比引用更多的信息,例如元数据,当前长度,最大可用长度等。引用和智能指针的另一个不同在于前者仅仅是借用了数据,而后者往往可以拥有它们指向的数据,然后再为其它人提供服务。智能指针往往是基于结构体实现,它与我们自定义的结构体最大的区别在于它实现了 Deref 和 Drop 特征:
zy010101
2023/05/09
1.2K0
Rust入坑指南:智能指针
在了解了Rust中的所有权、所有权借用、生命周期这些概念后,相信各位坑友对Rust已经有了比较深刻的认识了,今天又是一个连环坑,我们一起来把智能指针刨出来,一探究竟。
Jackeyzhe
2020/03/12
9320
【译】Rust与智能指针
如果你一直在订阅这个系列,关于所有权的那篇文章[1]可能给你带来了这种印象——Rust 确实是个好东西,C++不应该在生产环境中使用。智能指针可能会改变你的想法。用现代的话来说,Smart pointers 是指那些有点(嗯......)额外(东西)的指针。他们本质上还是管理其所指向的对象的内存地址,并且当对象不再被使用的时候会将其释放。这消除了很多因不恰当的内存管理而引起的 bug,并使得编程不再那么枯燥乏味。C++智能指针为原始指针提供了一个安全的替代方案,而 Rust 智能指针则在保证安全的前提下扩展了语言功能。
MikeLoveRust
2020/10/26
1.2K0
【译】Rust与智能指针
【Rust每周一知】理解智能指针Box<T>
指针是个通用概念,它表示内存地址这种类型,其引用或“指向”其他数据。Rust中的指针是“第一类公民”(first-class values),可以将它们移动或复制,存储到数据结构中并从函数中返回。Rust提供了多种类型的指针:
MikeLoveRust
2020/02/20
2.2K0
Rust编程学习笔记Day7-一个值可以有多个所有者吗?
我们之前介绍的单一所有权,其实已经能满足我们使用内存的大部分场景。在编译时就能完成静态检查,不会影响运行时的效率。
用户1072003
2023/02/23
1.1K0
Rust编程学习笔记Day7-一个值可以有多个所有者吗?
【Rust 基础篇】Rust 智能指针
在 Rust 中,智能指针是一种提供了额外功能的指针类型。智能指针可以在编译时和运行时检查内存安全,并提供了更灵活的所有权和借用模型。本篇博客将详细介绍 Rust 中的智能指针,包括常用的智能指针类型、创建和使用智能指针、内存安全和性能考虑等。
繁依Fanyi
2023/10/12
2870
Rust 总结
所有权是用来管理堆上内存的一种方式,在编译阶段就可以追踪堆内存的分配和释放,不会对程序的运行期造成任何性能上的损失。
谛听
2022/06/04
1.8K0
《Rust避坑式入门》第1章:挖数据竞争大坑的滥用可变性
赵可菲是一名Java程序员,一直在维护一个有十多年历史的老旧系统。这个系统即将被淘汰,代码质量也很差,每次上线都会出现很多bug,她不得不加班修复。公司给了她3个月的内部转岗期,如果转不出去就会被裁员。她得知公司可能会用Rust重写很多系统,于是就报名参加了公司的Rust培训,希望能够转型。
程序员吾真本
2024/08/29
6570
《Rust避坑式入门》第1章:挖数据竞争大坑的滥用可变性
【Rust精彩blog】Rust 中几个智能指针的异同与使用场景
想必写过 C 的程序员对指针都会有一种复杂的情感,与内存相处的过程中可以说是成也指针,败也指针。一不小心又越界访问了,一不小心又读到了内存里的脏数据,一不小心多线程读写数据又不一致了……我知道讲到这肯定会有人觉得“出这种问题还不是因为你菜”云云,但是有一句话说得好:“自由的代价就是需要时刻保持警惕”。
MikeLoveRust
2020/02/20
1.9K0
rust的内存管理
内存管理是rust最有意思的事情了。rust的内存管理有三条准则。 let分配资源 分配会转移所有权,比如赋值直接move了 值和变量在作用域末尾会被清理,释放 drop方法会在释放前调用 rust支持移动语义和复制语义,为此抽象出了两个trait,clone和copy 非堆内存可以使用copy,隐式转化,clone需要显示调用 关于借用的规则,使用& 一个引用的生命周期不能超过其被引用的时间 如果存在一个可变借用,不允许存在其他值 如果不存在可变借用,允许存在多个不可变借用 借用规则方法类型 &self
李子健
2022/05/08
7810
go 开发者的 rust 入门
即:在任意给定时间,要么 只能有一个可变引用,要么 只能有多个不可变引用。引用必须总是有效的。
王磊-字节跳动
2021/11/27
2K0
揭开智能指针 Box 的神秘面纱
熟悉 c++ 的肯定知道 shared_ptr, unique_ptr, 而 Rust 也有智能指针 Box, Rc, Arc, RefCell 等等,本文分享 Box 底层实现
MikeLoveRust
2021/08/13
6260
66个让你对Rust又爱又恨的场景之一:变量与值
属于手动内存管理流派的C++,虽然提供了手动管理内存的灵活性,但容易因程序员的失误导致内存泄漏、悬垂指针、双重释放和野指针等问题。
程序员吾真本
2024/07/18
6700
66个让你对Rust又爱又恨的场景之一:变量与值
Rust学习笔记Day18 智能指针Cow/MutexGuard
这是用于提供写时克隆(Clone-on-Write)的一个智能指针,和虚拟内存管理的写时复制很像。
用户1072003
2023/02/23
7430
Rust学习笔记Day18 智能指针Cow/MutexGuard
Rust学习笔记Day17 智能指针之Box<T>
经过这一段时间的学习,基础知识里,我们还剩数据结构没有学习,而数据结构里最难的就是智能指针。
用户1072003
2023/02/23
3910
Rust学习笔记Day17 智能指针之Box<T>
Rust避坑现代C++悬垂指针
C++是一门应用广泛的编程语言。在2023年JetBrains全球开发者生态问卷调查中,C++在受访程序员过去一年中的使用率,占25%,紧跟JavaScript、Python和Java之后。在本书撰写时,根据JetBrains的统计,程序员使用最多的是C++17。
程序员吾真本
2024/09/18
7532
Rust避坑现代C++悬垂指针
Rust中的一些标准库
Box 允许将一个值放在堆上而不是栈上,留在栈上的则是指向堆数据的指针。Box 是一个指向堆的智能指针,当一个 Box 超出作用域时,它的析构函数被调用,内部对象被销毁,堆上的内存被释放。
端碗吹水
2022/06/05
9840
Rust中的一些标准库
聊聊共享所有权之Rc和Arc
像如下代码,字符串a如果直接移动给b后就没法后边再去打印,因为它的所有权已经转移给了b。
newbmiao
2023/11/27
3690
聊聊共享所有权之Rc和Arc
Rust学习笔记Day11 类型系统及多态是如何实现的?
一门编程语言的类型系统会影响到开发者的形式和效率及程序员的安全性。 因为对于计算机而言,它并不知道有什么类型,最终执行的都是一条条指令,或与内存打交道,内存中的数据是字节流。
用户1072003
2023/02/23
1.1K0
Rust学习笔记Day11 类型系统及多态是如何实现的?
【Rust 基础篇】Rust 的 `Rc<RefCell<T>>` - 共享可变性的智能指针
在 Rust 中,Rc<RefCell<T>> 是一种组合智能指针,用于实现多所有权共享可变数据。Rc 允许多个所有者共享相同的数据,而 RefCell 允许在有多个引用的情况下对数据进行可变操作。
繁依Fanyi
2023/10/12
1K0
相关推荐
rust智能指针
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档