当前位置: 首页 > 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;每个区域都可以配置一个区域…...

高危文件识别的常用算法:原理、应用与企业场景

高危文件识别的常用算法&#xff1a;原理、应用与企业场景 高危文件识别旨在检测可能导致安全威胁的文件&#xff0c;如包含恶意代码、敏感数据或欺诈内容的文档&#xff0c;在企业协同办公环境中&#xff08;如Teams、Google Workspace&#xff09;尤为重要。结合大模型技术&…...

Cloudflare 从 Nginx 到 Pingora:性能、效率与安全的全面升级

在互联网的快速发展中&#xff0c;高性能、高效率和高安全性的网络服务成为了各大互联网基础设施提供商的核心追求。Cloudflare 作为全球领先的互联网安全和基础设施公司&#xff0c;近期做出了一个重大技术决策&#xff1a;弃用长期使用的 Nginx&#xff0c;转而采用其内部开发…...

CRMEB 框架中 PHP 上传扩展开发:涵盖本地上传及阿里云 OSS、腾讯云 COS、七牛云

目前已有本地上传、阿里云OSS上传、腾讯云COS上传、七牛云上传扩展 扩展入口文件 文件目录 crmeb\services\upload\Upload.php namespace crmeb\services\upload;use crmeb\basic\BaseManager; use think\facade\Config;/*** Class Upload* package crmeb\services\upload* …...

(转)什么是DockerCompose?它有什么作用?

一、什么是DockerCompose? DockerCompose可以基于Compose文件帮我们快速的部署分布式应用&#xff0c;而无需手动一个个创建和运行容器。 Compose文件是一个文本文件&#xff0c;通过指令定义集群中的每个容器如何运行。 DockerCompose就是把DockerFile转换成指令去运行。 …...

Maven 概述、安装、配置、仓库、私服详解

目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

虚拟电厂发展三大趋势:市场化、技术主导、车网互联

市场化&#xff1a;从政策驱动到多元盈利 政策全面赋能 2025年4月&#xff0c;国家发改委、能源局发布《关于加快推进虚拟电厂发展的指导意见》&#xff0c;首次明确虚拟电厂为“独立市场主体”&#xff0c;提出硬性目标&#xff1a;2027年全国调节能力≥2000万千瓦&#xff0…...

力扣热题100 k个一组反转链表题解

题目: 代码: func reverseKGroup(head *ListNode, k int) *ListNode {cur : headfor i : 0; i < k; i {if cur nil {return head}cur cur.Next}newHead : reverse(head, cur)head.Next reverseKGroup(cur, k)return newHead }func reverse(start, end *ListNode) *ListN…...

Webpack性能优化:构建速度与体积优化策略

一、构建速度优化 1、​​升级Webpack和Node.js​​ ​​优化效果​​&#xff1a;Webpack 4比Webpack 3构建时间降低60%-98%。​​原因​​&#xff1a; V8引擎优化&#xff08;for of替代forEach、Map/Set替代Object&#xff09;。默认使用更快的md4哈希算法。AST直接从Loa…...

elementUI点击浏览table所选行数据查看文档

项目场景&#xff1a; table按照要求特定的数据变成按钮可以点击 解决方案&#xff1a; <el-table-columnprop"mlname"label"名称"align"center"width"180"><template slot-scope"scope"><el-buttonv-if&qu…...

【Elasticsearch】Elasticsearch 在大数据生态圈的地位 实践经验

Elasticsearch 在大数据生态圈的地位 & 实践经验 1.Elasticsearch 的优势1.1 Elasticsearch 解决的核心问题1.1.1 传统方案的短板1.1.2 Elasticsearch 的解决方案 1.2 与大数据组件的对比优势1.3 关键优势技术支撑1.4 Elasticsearch 的竞品1.4.1 全文搜索领域1.4.2 日志分析…...