当前位置: 首页 > news >正文

Rust8.1 Smart Pointers

Rust学习笔记

Rust编程语言入门教程课程笔记

参考教材: The Rust Programming Language (by Steve Klabnik and Carol Nichols, with contributions from the Rust Community)

Lecture 15: Smart Pointers

src/main.rs

use crate::List::{Cons, Nil};
use std::ops::Deref;
use crate::RcList::{RcCons, RcNil};
use std::rc::Rc;
use std::cell::RefCell;
use crate::List2::{Cons2, Nil2};
use crate::List3::{Cons3, Nil3};
use std::rc::Weak;fn main() {//reference counting//Rc<T> allows multiple ownership of immutable data//Example: String and Vec<T>//Trait//Deref: allows an instance of a smart pointer to behave like a reference//Drop: allows you to customize the code that is run when an instance of the smart pointer goes out of scope//The most common smart pointers in the standard library//Box<T> for allocating values on the heap//Rc<T>, a reference counting type that enables multiple ownership//Ref<T> and RefMut<T>, accessed through RefCell<T>, a type that enforces the borrowing rules at runtime instead of compile time//Box<T>let b = Box::new(5);println!("b = {}", b);//Recursive Typeslet _list = Cons(1, Box::new(Cons(2, Box::new(Cons(3, Box::new(Nil))))));//Deref Trait//If a struct implements the Deref trait, we can use the * operator//to dereference an instance of that struct//Rust will analyze the types and use Deref::deref as many times as necessary//to get a reference to match the parameter's typelet x = 5;let y = &x;let z = Box::new(x);let zz = MyBox::new(x);assert_eq!(5, x);assert_eq!(5, *y);assert_eq!(5, *z);assert_eq!(5, *zz);//Deref coercion//Rust does deref coercion when it finds types and trait implementations in three cases://From &T to &U when T: Deref<Target=U>let m = MyBox::new(String::from("Rust"));hello(&m);//hello(&(*m)[..]);hello("Rust");//Drop Trait //in the preludelet c = CustomSmartPointer { data: String::from("my stuff") };drop(c);//force a value to be dropped sooner than the end of its scopelet d = CustomSmartPointer { data: String::from("other stuff") };println!("CustomSmartPointers created.");//Output://CustomSmartPointers created.//Dropping CustomSmartPointer with data `other stuff`!//Dropping CustomSmartPointer with data `my stuff`!//Rust automatically called drop for us when our instances went out of scope, //calling the code we specified. //Variables are dropped in the reverse order of their creation, so d was dropped before c.//Rc<T> Reference Counted Smart Pointer//Rc<T> enables multiple owners of the same data; Box<T> and RefCell<T> have single owners.//Rc<T> keeps track of the number of references to a value which determines whether or not a value is still in use.//If there are zero references to a value, the value can be cleaned up without any references becoming invalid.//Rc<T> is only for use in single-threaded scenarios.//Rc<T> is only for use in single-threaded scenarioslet list_a = Rc::new(RcCons(5, Rc::new(RcCons(10, Rc::new(RcNil)))));println!("count after creating list_a = {}", Rc::strong_count(&list_a));//1let list_b = RcCons(3, Rc::clone(&list_a));//Rc::clone doesn't make a deep copy of all the data like most types' implementations of clone do.println!("count after creating list_b = {}", Rc::strong_count(&list_a));//2{let list_c = RcCons(4, Rc::clone(&list_a));println!("count after creating list_c = {}", Rc::strong_count(&list_a));//3}println!("count after list_c goes out of scope = {}", Rc::strong_count(&list_a));//2//RefCell<T> and the Interior Mutability Pattern//RefCell<T> is useful when you’re sure your code follows the borrowing rules but the compiler is unable to understand and guarantee that.//RefCell<T> can only be used in single-threaded scenarios.let value = Rc::new(RefCell::new(5));let a = Rc::new(Cons2(Rc::clone(&value), Rc::new(Nil2)));let b = Cons2(Rc::new(RefCell::new(6)), Rc::clone(&a));let c = Cons2(Rc::new(RefCell::new(10)), Rc::clone(&a));*value.borrow_mut() += 10;//borrow_mut returns a RefMut<T> smart pointerprintln!("a after = {:?}", a);println!("b after = {:?}", b);println!("c after = {:?}", c);//Other Smart Pointers//Cell<T>: a type that internally uses RefCell<T> but also can be copied//Mutex<T>: a type of smart pointer that locks access to the inner data using a mutex//Reference Cycles Can Leak Memory//Rc<T> allows you to have multiple owners of some data, but it doesn’t let you mutate that data.//If we want to mutate data, we need to use the interior mutability pattern.//RefCell<T> allows us to mutate contents inside an Rc<T>.//RefCell<T> keeps track of how many Ref<T> and RefMut<T> smart pointers are currently active.//When either kind of smart pointer is dropped, RefCell<T> will decrease the count of the number of smart pointers that are active.//When the count of either goes back to zero, the RefCell<T> will reclaim its inner value.let a = Rc::new(Cons3(5, RefCell::new(Rc::new(Nil3))));println!("a initial rc count = {}", Rc::strong_count(&a));//1println!("a next item = {:?}", a.tail());//Some(RefCell { value: Nil3 })let b = Rc::new(Cons3(10, RefCell::new(Rc::clone(&a))));println!("a rc count after b creation = {}", Rc::strong_count(&a));//2println!("b initial rc count = {}", Rc::strong_count(&b));//1println!("b next item = {:?}", b.tail());//Some(RefCell { value: Cons3(5, RefCell { value: Nil3 }) })if let Some(link) = a.tail() {*link.borrow_mut() = Rc::clone(&b);} println!("b rc count after changing a = {}", Rc::strong_count(&b));//2println!("a rc count after changing a = {}", Rc::strong_count(&a));//2//println!("a next item = {:?}", a.tail());//Some(RefCell { value: Cons3(10, RefCell { value: Cons3(5, RefCell { value: Cons3(10, RefCell { value: Nil3 }) }) }) })//Weak Referenceslet leaf = Rc::new(Node {value: 3,parent: RefCell::new(Weak::new()),//Weak::new() creates a Weak<T> that doesn’t have an ownerchildren: RefCell::new(vec![]),});println!("leaf strong = {}, weak = {}", Rc::strong_count(&leaf), Rc::weak_count(&leaf));//1, 0println!("leaf parent = {:?}", leaf.parent.borrow().upgrade());//None{let branch = Rc::new(Node {value: 5,parent: RefCell::new(Weak::new()),//Weak::new() creates a Weak<T> that doesn’t have an ownerchildren: RefCell::new(vec![Rc::clone(&leaf)]),});*leaf.parent.borrow_mut() = Rc::downgrade(&branch);//Rc::downgrade creates a Weak<T> from a Rc<T> referenceprintln!("branch strong = {}, weak = {}", Rc::strong_count(&branch), Rc::weak_count(&branch));//1, 1println!("leaf strong = {}, weak = {}", Rc::strong_count(&leaf), Rc::weak_count(&leaf));//2, 0}println!("leaf parent = {:?}", leaf.parent.borrow().upgrade());//Some(Node { value: 5, parent: RefCell { value: None }, children: RefCell { value: [Node { value: 3, parent: RefCell { value: None }, children: RefCell { value: [] } }] } })println!("leaf strong = {}, weak = {}", Rc::strong_count(&leaf), Rc::weak_count(&leaf));//1, 0
}//Recursive Types
enum List {Cons(i32, Box<List>),//Box<List> is a pointer to another List. This has a known size.Nil,
}//define a smart pointer
struct MyBox<T>(T);//implement Deref trait for MyBox<T>
impl<T> MyBox<T> {fn new(x: T) -> MyBox<T> {MyBox(x)}
}impl<T> Deref for MyBox<T> {//implement Deref trait for MyBox<T>type Target = T;//associated type for the Deref trait to usefn deref(&self) -> &T {//return a reference to the value we want to access with the * operator&self.0}
}fn hello(name: &str) {println!("Hello, {}!", name);
}struct CustomSmartPointer {data: String,
}impl Drop for CustomSmartPointer {//implement Drop traitfn drop(&mut self) {//drop methodprintln!("Dropping CustomSmartPointer with data `{}`!", self.data);}
}enum RcList {RcCons(i32, Rc<RcList>),RcNil,
}pub trait Messenger {fn send(&self, msg: &str);}pub struct LimitTracker<'a, T: Messenger> {messenger: &'a T,value: usize,max: usize,
}impl <'a, T> LimitTracker<'a, T> 
whereT: Messenger,
{pub fn new(messenger: &T, max: usize) -> LimitTracker<T> {LimitTracker {messenger,//messenger: messenger,value: 0,max,}}pub fn set_value(&mut self, value: usize) {self.value = value;let percentage_of_max = self.value as f64 / self.max as f64;if percentage_of_max >= 1.0 {self.messenger.send("Error: You are over your quota!");} else if percentage_of_max >= 0.9 {self.messenger.send("Urgent warning: You've used up over 90% of your quota!");} else if percentage_of_max >= 0.75 {self.messenger.send("Warning: You've used up over 75% of your quota!");}}
}#[derive(Debug)]
enum List2 {Cons2(Rc<RefCell<i32>>, Rc<List2>),Nil2,
}#[derive(Debug)]
enum List3 {Cons3(i32, RefCell<Rc<List3>>),Nil3,
}impl List3 {fn tail(&self) -> Option<&RefCell<Rc<List3>>> {match self {Cons3(_, item) => Some(item),Nil3 => None,}}}#[derive(Debug)]
struct Node {value: i32,parent: RefCell<Weak<Node>>,children: RefCell<Vec<Rc<Node>>>,}#[cfg(test)]
mod tests {use super::*;struct MockMessenger {sent_messages: RefCell<Vec<String>>,}impl MockMessenger {fn new() -> MockMessenger {MockMessenger { sent_messages: RefCell::new(vec![])}}}impl Messenger for MockMessenger {fn send(&self, message: &str) {self.sent_messages.borrow_mut().push(String::from(message));//borrow_mut returns a RefMut<T> smart pointer//Every time we call borrow_mut, the mutable borrow counter goes up by one.//When a RefMut<T> value goes out of scope, the mutable borrow counter goes down by one.}}#[test]fn it_sends_an_over_75_percent_warning_message() {let mock_messenger = MockMessenger::new();let mut limit_tracker = LimitTracker::new(&mock_messenger, 100);limit_tracker.set_value(80);assert_eq!(mock_messenger.sent_messages.borrow().len(), 1);//borrow returns a Ref<T> smart pointer//Every time we call borrow, the immutable borrow counter goes up by one.//When a Ref<T> value goes out of scope, the immutable borrow counter goes down by one.}
}

相关文章:

Rust8.1 Smart Pointers

Rust学习笔记 Rust编程语言入门教程课程笔记 参考教材: The Rust Programming Language (by Steve Klabnik and Carol Nichols, with contributions from the Rust Community) Lecture 15: Smart Pointers src/main.rs use crate::List::{Cons, Nil}; use std::ops::Deref…...

MATLAB与Excel的数据交互

准备阶段 clear all % 添加Excel函数 try Excel=actxGetRunningServer(Excel.Application); catch Excel=actxserver(Excel.application); end % 设置Excel可见 Excel.visible=1; 插入数据 % % 激活eSheet1 % eSheet1.Activate; % 或者 % Activate(eSheet1); % % 打开…...

使用.NET 4.0、3.5时,UnmanagedFunctionPointer导致堆栈溢出

本文介绍了使用.NET 4.0、3.5时&#xff0c;UnmanagedFunctionPointer导致堆栈溢出的处理方法&#xff0c;对大家解决问题具有一定的参考价值&#xff0c;需要的朋友们下面随着小编来一起学习吧&#xff01; 问题描述 我在带有try catch块的点击处理程序中有一个简单的函数。…...

jbase打印导出实现

上一篇实现了虚拟M层&#xff0c;这篇基于虚拟M实现打印导出。 首先对接打印层 using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Text; using System.Threading.Tasks; using System.Xml;namesp…...

特征缩放和转换以及自定义Transformers(Machine Learning 研习之九)

特征缩放和转换 您需要应用于数据的最重要的转换之一是功能扩展。除了少数例外&#xff0c;机器学习算法在输入数值属性具有非常不同的尺度时表现不佳。住房数据就是这种情况:房间总数约为6至39320间&#xff0c;而收入中位数仅为0至15间。如果没有任何缩放&#xff0c;大多数…...

前端算法面试之堆排序-每日一练

如果对前端八股文感兴趣&#xff0c;可以留意公重号&#xff1a;码农补给站&#xff0c;总有你要的干货。 今天分享一个非常热门的算法--堆排序。堆的运用非常的广泛&#xff0c;例如&#xff0c;Python中的heapq模块提供了堆排序算法&#xff0c;可以用于实现优先队列&#xf…...

C++之set/multise容器

C之set/multise容器 set基本概念 set构造和赋值 #include <iostream> #include<set> using namespace std;void PrintfSet(set<int>&s) {for(set<int>::iterator it s.begin();it ! s.end();it){cout<<*it<<" ";}cout&l…...

本地部署AutoGPT

我们都了解ChatGPT&#xff0c;是Openai退出的基于GPT模型的新一代 AI助手&#xff0c;可以帮助解决我们在多个领域的问题。但是你会发现&#xff0c;在某些问题上&#xff0c;ChatGPT 需要经过不断的调教与沟通&#xff0c;才能得到接近正确的答案。对于你不太了解的领域领域&…...

ProtocolBuffers(protobuf)详解

目录 前言特点语法定义关键字JSON与Protocol Buffers互相转换gRPC与Protocol Buffers的关系 前言 Protocol Buffers&#xff08;通常简称为protobuf&#xff09;是Google公司开发的一种数据描述语言&#xff0c;它能够将结构化数据序列化&#xff0c;可用于数据存储、通信协议…...

HTTP 到 HTTPS 再到 HSTS 的转变

近些年&#xff0c;随着域名劫持、信息泄漏等网络安全事件的频繁发生&#xff0c;网站安全也变得越来越重要&#xff0c;也促成了网络传输协议从 HTTP 到 HTTPS 再到 HSTS 的转变。 HTTP HTTP&#xff08;超文本传输协议&#xff09; 是一种用于分布式、协作式和超媒体信息系…...

清华学霸告诉你:如何自学人工智能?

清华大学作为中国顶尖的学府之一&#xff0c;培养了许多优秀的人才&#xff0c;其中不乏在人工智能领域有所成就的学霸。通过一位清华学霸的经验分享&#xff0c;揭示如何自学人工智能&#xff0c;帮助你在这场科技浪潮中勇往直前。 一、夯实基础知识 数学基础&#xff1a;学习…...

Ubuntu 安装VMware Tools选项显示灰色,如何安装VMware Tools

切换apt源为阿里云&#xff1a; https://qq742971636.blog.csdn.net/article/details/134291339 只要你的网络没问题&#xff0c;你直接执行这几个命令&#xff0c;重启ubuntu虚拟机即可、 sudo dpkg --configure -a sudo apt-get autoremove open-vm-tools sudo apt-get ins…...

SpringBoot 2.x 实战仿B站高性能后端项目

SpringBoot 2.x 实战仿B站高性能后端项目 下栽の地止&#xff1a;请看文章末尾 通常SpringBoot新建项目&#xff0c;默认是集成了Maven&#xff0c;然后所有内容都在一个主模块中。 如果项目架构稍微复杂一点&#xff0c;就需要用到Maven多模块。 本文简单概述一下&#xff0c…...

vscode文件夹折叠问题

今天发现一个vscode的文件夹显示的问题&#xff0c;首先是这样的&#xff0c;就是我的文件夹里又一个子文件夹&#xff0c;子文件夹里有一些文件&#xff0c;但是我发现无法折叠起这个子文件夹&#xff0c;总是显示全部的文件&#xff0c;这让我备份很难&#xff0c;具体参考 h…...

4-flask-cbv源码、Jinja2模板、请求响应、flask中的session、flask项目参考

1 flask中cbv源码 2 Jinja2模板 3 请求响应 4 flask中的session 5 flask项目参考 1 flask中cbv源码 ***flask的官网文档&#xff1a;***https://flask.palletsprojects.com/en/3.0.x/views/1 cbv源码执行流程1 请求来了&#xff0c;路由匹配成功---》执行ItemAPI.as_view(item…...

2.Pandas数据预处理

2.1 数据清洗 以titanic数据为例。 df pd.read_csv(titanic.csv) 2.1.1 缺失值 &#xff08;1&#xff09;缺失判断 df.isnull() &#xff08;2&#xff09;缺失统计 # 列缺失统计 df.isnull().sum(axis0) # 行缺失统计 df.isnull().sum(axis1) # 统计缺失率 df.isnu…...

C# IEnumerable<T>介绍

IEnumerable 是 C# 中的一个接口&#xff0c;它是 .NET Framework 中的集合类型的基础。任何实现了 IEnumerable 接口的对象都可以进行 foreach 迭代。 IEnumerable 只有一个方法&#xff0c;即 GetEnumerator&#xff0c;该方法返回一个 IEnumerator 对象。IEnumerator 对象用…...

九洲

《九洲》 作者&#xff0f;罗光记 九洲春色映朝阳&#xff0c; 洲渚风光似画廊。 柳絮飘飞花似雪&#xff0c; 九州繁华共锦裳。 水波荡漾鱼儿跃&#xff0c; 洲边鸟语唤晨光。 春风拂过千里岸&#xff0c; 九洲儿女笑语扬。...

基于Genio 700 (MT8390)芯片的AR智能眼镜方案

AR眼镜是一种具有前所未有发展机遇的设备&#xff0c;无论是显示效果、体积还是功能都有明显的提升。AR技术因其智能、实时、三维、多重交互和开放世界的特点备受关注。 AR眼镜集成了AR技术、语音识别、智能控制等多项高科技功能&#xff0c;可以帮助用户实现更加便捷、高效、个…...

锐捷OSPF认证

一、知识补充 1、基本概述 OSPF区域认证和端口认证是两种不同的认证机制&#xff0c;用于增强OSPF协议的安全性。 OSPF区域认证&#xff08;OSPF Area Authentication&#xff09;&#xff1a;这种认证机制是基于区域的。在OSPF网络中&#xff0c;每个区域都可以配置一个区域…...

告别复杂配置,使用Taotoken CLI一键生成多工具环境配置文件

&#x1f680; 告别海外账号与网络限制&#xff01;稳定直连全球优质大模型&#xff0c;限时半价接入中。 &#x1f449; 点击领取海量免费额度 告别复杂配置&#xff0c;使用Taotoken CLI一键生成多工具环境配置文件 在接入多个大模型工具时&#xff0c;开发者常常需要为每个…...

Upscayl终极指南:如何用免费AI工具让模糊图片变高清

Upscayl终极指南&#xff1a;如何用免费AI工具让模糊图片变高清 【免费下载链接】upscayl &#x1f199; Upscayl - #1 Free and Open Source AI Image Upscaler for Linux, MacOS and Windows. 项目地址: https://gitcode.com/GitHub_Trending/up/upscayl 你是否曾因照…...

Petrel地质建模许可不够用?自动回收,油气勘探团队高效

你是不是也遇到这种情况&#xff1f;项目组突然来了个新成员&#xff0c;结果所有许可都满了&#xff0c;连老员工都得排队等。别慌&#xff0c;我搞懂了&#xff0c;Petrel许可不够用&#xff0c;最大的问题就是没回收&#xff0c;几十万的授权就浪费在没人用的角落。 闲置许…...

5分钟学会:用SlopeCraft制作惊艳的Minecraft立体地图画终极指南

5分钟学会&#xff1a;用SlopeCraft制作惊艳的Minecraft立体地图画终极指南 【免费下载链接】SlopeCraft Map Pixel Art Generator for Minecraft 项目地址: https://gitcode.com/gh_mirrors/sl/SlopeCraft 你是否曾想将心爱的照片或艺术作品变成Minecraft世界中的立体艺…...

某供应链企业200GB数据泄露复盘:如果开了透明加密,攻击者拿走的只有乱码

图&#xff1a;供应链企业数据泄露的3条典型路径&#xff08;U盘导出/数据库导出/截图&#xff09;与TDE透明加密的拦截机制事件还原&#xff1a;一次"完美"的内部数据窃取说明&#xff1a;以下事件基于多起真实安全事件综合脱敏处理&#xff0c;技术细节均为真实攻击…...

SD-PPP:革命性Photoshop AI插件,彻底终结设计工作流断层

SD-PPP&#xff1a;革命性Photoshop AI插件&#xff0c;彻底终结设计工作流断层 【免费下载链接】sd-ppp A Photoshop AI plugin 项目地址: https://gitcode.com/gh_mirrors/sd/sd-ppp 还在Photoshop与AI绘图工具之间手动搬运素材吗&#xff1f;SD-PPP是一款开源免费的P…...

保姆级教程:Win10/Win11下彻底解决原神启动器Qt插件初始化失败(附环境变量排查与恢复指南)

深度解析Windows环境下Qt插件初始化失败的终极解决方案 当你在Windows 10或11系统上双击原神启动器&#xff0c;却看到"no Qt platform plugin could be initialized"的错误提示时&#xff0c;那种挫败感不言而喻。这个问题看似简单&#xff0c;实则涉及系统环境变量…...

什么是数字员工?AI销冠系统与AI提效软件系统在提升销售效率中的关键角色是什么?

数字员工成为一种新兴的AI销售工具&#xff0c;正在为企业优化业务流程和提升运营效率提供巨大助力。这些智能化的虚拟职员能够处理大量的客户咨询&#xff0c;全天候地维护客户关系&#xff0c;显著减少了人力资源的消耗。依靠AI销冠系统&#xff0c;这些数字员工除了实时分析…...

AArch64架构TLB管理机制与优化实践

1. AArch64 TLB管理机制概述TLB&#xff08;Translation Lookaside Buffer&#xff09;是现代处理器内存管理单元&#xff08;MMU&#xff09;的核心组件&#xff0c;负责缓存虚拟地址到物理地址的转换结果。在AArch64架构中&#xff0c;TLB管理机制尤为复杂&#xff0c;涉及多…...

别再手动刷纹理了!用Blender 3.6的镂版映射,5分钟给苹果模型贴上真实贴图

别再手动刷纹理了&#xff01;Blender 3.6镂版映射实战指南 在数字艺术创作中&#xff0c;给3D模型添加纹理是赋予物体真实感的关键步骤。许多Blender初学者在掌握了基础UV展开后&#xff0c;往往会陷入手动绘制纹理的低效循环——用笔刷一点一点"涂抹"贴图&#xff…...