【CS110L】Rust语言 Lecture3-4 笔记

文章目录

    • 第三讲 所有权:移动与借用&
          • 例1
          • 例2
          • 例3
      • 错误处理(开头)
          • 为什么空指针如此危险,我们能做什么以应对?— 引出Option
          • is_none()函数
          • unwrap_or()函数
          • 常见用法
    • 第四讲 代码实践:链表
          • Box
          • 节点和链表的定义
          • 节点和链表的构造函数
          • 判空 得到size
          • 插:take
          • Push Pop

第三讲 所有权:移动与借用&

为什么学习Rust?— 为了写出更安全的c/c++代码。Rust是人们对于c/c++缺点的回应,这个回应也有一些不足。

有些库会自己释放,给你指针,你不能用free,而是库提供的

一个包含了指向内存其他地方的指针的结构体的所有权传递问题在Rust和c/c++中都是有挑战的。Rust在编译时强迫你解决清除所有所有权的问题。

例1
// eg1.rs
fn main() {let s = String::from("hello");s.push_str(" world");
}

错,改为let **mut** s = String::from("hello");

例2
//eg2.rs
fn om_nom_nom(s: String) {println!("{}", s);// 释放s
}fn main() {let s = String::from("hello");om_nom_nom(s);// 到这里s的生命周期就结束了om_nom_nom(s);
}

错。相比以下c代码,free有四种放置方式,都可以通过编译。但只有一种是正确的。其余都会在运行时出现漏洞。

Rust起初感觉上是反直觉的,但是不容易错的。

//eg2.c
void om_nom_nom(char* s) {printf("%s\n", s);
}
int main() {char* s = strup("hello");om_nom_nom(s);om_nom_nom(s);free(s);
}

eg2.rs改法:

//eg2.rs
fn om_nom_nom(s: &String) {println!("{}", s);
}fn main() {let s = String::from("hello");om_nom_nom(&s); // 传引用om_nom_nom(&s);// s在这里释放
}
例3
// eg3.rs
fn main() {let s = String::from("hello");let s1 = &s;let s2 = &s;println!("{} {} {}", s, s1, s2);
}

对,s1 s2都是不可更改的副本

// eg3.rs
fn main() {let mut s = String::from("hello");let s1 = &mut s;let s2 = s;println!("{} {} {}", s, s1, s2);
}

错,rust的引用模型就是只有一个可改的,或者多个不可改的

// eg3.rs
fn main() {let mut s = String::from("hello");let s1 = &mut s;println!("{} {}", s, s1);
}

错, Rust 的借用规则不允许在同一作用域内同时存在可变引用和原始变量

// eg3.rs
fn main() {let mut s = String::from("hello");let s1 = &mut s;println!("{} {}", s1);println!("{} {}", s);
}

对,编译器看到了在使用s1时没有用过s,那就可以

// eg3.rs
fn main() {let mut s = String::from("hello");let s1 = &mut s;println!("{} {}", s);println!("{} {}", s1);
}

错误处理(开头)

Q:这段代码哪里有问题?
在这里插入图片描述
A:(本节课只讲第一点 —— 空指针)
在这里插入图片描述

为什么空指针如此危险,我们能做什么以应对?— 引出Option

None和值不会混在一起。

fn feeling_lucky() -> Option<String> {if get_random_num() > 10 {Some(String::from("lucky"))} else {None}
}
is_none()函数

if feeling_lucky().is_none()

unwrap_or()函数

let message = feeling_lucky().unwrap_or(String::from("No lucky"));

常见用法
match feeling_lucky() {Some(message) => {println!("Got message: {}", message);},None => {println!("No message returned.");}
}

第四讲 代码实践:链表

Box

在堆上分配,类似于c++的unique_ptr,优点:指针超出作用域后销毁,那块内存自动释放。

fn main() {let x: Box<u32> = Box::new(10);println!("{}", *x); // *x改为x,输出同样是10,因为自动解引用
}
// 输出:10
节点和链表的定义
struct LinkedList {head : Option<Box<Node>>, // ,size : usize,
}struct Node {value : u32,next : Option<Box<Node>>,
}

Q: next : Box<&Node> 行吗?

A:不行。我们在这里需要的是实际拥有下一个节点,不然考虑你从哪里借用。一个Box就是一个指针,指向heap上某处的拥有指针。只要Box存活(指在生命周期内),Node必须存活。

节点和链表的构造函数
impl Node {pub fn new(value: u32, next: Option<Box<Node>>) -> Node {Node {value: value, next: next}}
}impl LinkedList {pub fn new() -> LinkedList {LinkedList {head: None, size: 0}}
}
判空 得到size
pub fn get_size(&self) -> usize {self.size // (*self).size 也可。从习惯上讲,不需要的话不要显式解引用
}pub fn is_empty(&self) -> bool {self.size == 0
}
插:take
let mut x : Option<u32> = Some(5);
let x_ref : &mut Option<u32> = &mut x;
println!("{:?}", x_ref.take());
println!("{:?}", x);
// Some(5)
// None
Push Pop
pub fn push(&mut self, value: u32) {let tmp_node: Box<Node> = Box::new(Node::new(value, self.head.take()));self.head = Some(tmp_node); // 此Some对应head的类型是Optionself.size += 1;
}pub fn pop(&mut self) -> Option<u32> {let tmp_node: Box<Node> = self.head.take()?; //问号self.head = tmp_node.next;Some(tmp_node.value) // 此Some对应返回值的Option
}

关于?符号的解释:? 是错误传播操作符,它用于在遇到 Err 值时提前退出函数,并返回错误。当 ? 被用于 Option 类型时,如果 OptionNone,那么它会导致函数返回 None,并且提前退出函数。如果 OptionSome(value),那么 ? 会提取出 value 并继续执行。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/53903.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

charls基于夜神模拟器抓取安卓7.0应用程序https请求

charls基于夜神模拟器抓取安卓7.0应用程序https请求 1、安装charls(安装步骤这里就不详细说了)2、下载证书(证书后缀名 xx.pem)3、使用git bash生成证书hash4、上传证书到安卓的系统证书目录下(夜神模拟器方案)5、验证抓包1、安装charls(安装步骤这里就不详细说了) 2、…

【Vue】2

1 Vue 生命周期 Vue生命周期&#xff1a;一个 Vue 实例从 创建 到 销毁 的整个过程 创建(create)阶段&#xff1a;组件实例化时&#xff0c;初始化数据、事件、计算属性等挂载(mount)阶段&#xff1a;将模板渲染并挂载到 DOM 上更新(update)阶段&#xff1a;当数据发生变化时…

fly专享

要逐步熟悉实验中的各个步骤&#xff0c;下面是详细的说明&#xff0c;包括如何下载软件以及相关操作步骤。 1. 熟悉VMware 15虚拟机的使用 步骤说明&#xff1a; 下载VMware Workstation 15&#xff1a; 打开浏览器&#xff0c;访问VMware官方网站&#xff1a;VMware Workst…

brpc的简单使用

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言大体流程一、编写.proto文件二、服务端搭建1.继承EchoService创建一个子类&#xff0c;并重写业务方法2.构造服务器对象3.向服务器对象中&#xff0c;新增EchoS…

String/StringBuffer/StringBuilder的区别

1.是什么 在Java中&#xff0c;String、StringBuffer、和StringBuilder都是用于处理字符串的类&#xff0c;但它们之间存在一些关键的区别&#xff0c;特别是在可变性、线程安全性以及性能方面。 1. String 不可变性&#xff1a;String对象是不可变的&#xff0c;这意味着一旦…

数据中台建设(六)—— 数据开发-提取数据价值

数据开发-提取数据价值 数据开发涉及的产品能力主要包括三部分&#xff1a;离线开发、实时开发和算法开发。 离线开发主要包括离线数据的加工、发布、运维管理&#xff0c;以及数据分析、数据探索、在线查询和及时分析相关工作。实时开发主要涉及数据的实时接入和实时处理。算…

golang学习笔记14——golang性能问题的处理方法

推荐学习文档 基于golang开发的一款超有个性的旅游计划app经历golang实战大纲golang优秀开发常用开源库汇总golang学习笔记01——基本数据类型golang学习笔记02——gin框架及基本原理golang学习笔记03——gin框架的核心数据结构golang学习笔记04——如何真正写好Golang代码&…

网络高级(学习)2024.9.10

目录 一、Modbus简介 1.起源 2.特点 3.应用场景 二、Modbus TCP协议 1.特点 2.协议格式 3.MBAP报文头 4.功能码 5.寄存器 &#xff08;1&#xff09;线圈寄存器&#xff0c;类比为开关量&#xff0c;每一个bit都对应一个信号的开关状态。 &#xff08;2&#xff09…

[项目实战]EOS多节点部署

文章总览&#xff1a;YuanDaiMa2048博客文章总览 EOS多节点部署 &#xff08;一&#xff09;环境设计&#xff08;二&#xff09;节点配置&#xff08;三&#xff09;区块信息同步&#xff08;四&#xff09;启动节点并验证同步EOS单节点的环境如何配置 &#xff08;一&#xf…

第十一周:机器学习

目录 摘要 Abstract 一、字符级的RNN进行名字分类 1、准备数据 2、构造神经网络 3、训练 4、评价结果 5、预测 二、字符级的RNN生成名字 1、准备数据 2、构造神经网络 3、训练 4、网络采样&#xff08;预测&#xff09; 三、batch normalization 1、 feature n…

【Go】十五、分布式系统、Consul服务注册发现、Nacos配置中心搭建

分布式 传统开发方式的痛点&#xff1a; 我们的服务分为很多种&#xff1a;用户服务、商品服务、订单服务等&#xff0c;若我们一个成熟的体系内&#xff0c;新添加一个服务&#xff0c;会变得十分的繁琐与困难 当我们的负载较大时&#xff0c;如果选择添加机器的方式来减轻…

Bootstrap 警告信息(Alerts)使用介绍

本章将讲解警告&#xff08;Alerts&#xff09;以及 Bootstrap 所提供的用于警告的 class。警告&#xff08;Alerts&#xff09;向用户提供了一种定义消息样式的方式。它们为典型的用户操作提供了上下文信息反馈。 您可以为警告框添加一个可选的关闭按钮。为了创建一个内联的可…

在Flask中实现跨域请求(CORS)

在Flask中实现跨域请求&#xff08;CORS&#xff0c;Cross-Origin Resource Sharing&#xff09;主要涉及到对Flask应用的配置&#xff0c;以允许来自不同源的请求访问服务器上的资源。以下是在Flask中实现CORS的详细步骤和方法&#xff1a; 一、理解CORS CORS是一种机制&…

HTTP 请求处理的完整流程到Servlet流程图

HTTP 请求处理的完整流程。从 TCP 三次握手开始&#xff0c;一直到 Servlet 处理请求并返回响应。 首先&#xff0c;让我解释一下 response.setContentType("text/html;charsetUTF-8"); 这行代码&#xff1a; 这行代码设置了 HTTP 响应的 Content-Type 头。它告诉浏…

【工具箱】NAND NOR FLASH闪存

随着国内集成电路的发展&#xff0c;特别是存储芯片方面&#xff0c;关于NOR Flash&#xff0c;NAND Flash&#xff0c;SD NAND, eMMC, Raw NAND的资料越来越多了。这里我专门写了这篇文章&#xff1a;1&#xff0c;把常用的存储产品做了分类; 2&#xff0c;把这些产品的特点做…

[Postman]接口自动化测试入门

文章大多用作个人学习分享&#xff0c;如果大家觉得有不足或错漏的地方欢迎评论指出或补充 此文章将完整的走一遍一个web页面的接口测试流程 大致路径为&#xff1a; 创建集合->调用接口登录获取token->保存token->带着token去完成其他接口的自动化测试->断言-&g…

Kafka下载与安装教程(国产化生产环境无联网服务器部署实操)

请放心观看&#xff0c;已在正式环境部署验证&#xff0c;流程无问题&#xff01; 所用系统为国产化麒麟银河 aarch64系统&#xff0c;部署时间2024年9月份&#xff01; [rootecs-xxxxxx-xxx ~]# cat /etc/os-release NAME"Kylin Linux Advanced Server" VERSION&q…

MySQL 查询数据库的数据总量

需求&#xff1a;查看MySQL数据库的数据总量&#xff0c;以MB为单位展示数据库占用的磁盘空间 实践&#xff1a; 登录到MySQL数据库服务器。 选择你想要查看数据总量的数据库&#xff1a; USE shield;运行查询以获取数据库的总大小&#xff1a; SELECT table_schema AS Datab…

go语言后端开发学习(七)——如何在gin框架中集成限流中间件

一.什么是限流 限流又称为流量控制&#xff08;流控&#xff09;&#xff0c;通常是指限制到达系统的并发请求数。 我们生活中也会经常遇到限流的场景&#xff0c;比如&#xff1a;某景区限制每日进入景区的游客数量为8万人&#xff1b;沙河地铁站早高峰通过站外排队逐一放行的…

Go 中 Gin 框架的使用指南

Gin 是 Go 语言中一个非常流行的 Web 框架&#xff0c;因其性能优异、简单易用的 API 设计而受到开发者的喜爱。Gin 的优势在于其高效的路由处理和中间件机制&#xff0c;适用于构建 RESTful API 和其他 Web 应用。本文将介绍如何使用 Gin 框架开发一个简单的 Web 应用&#xf…