【CS110L】Rust语言 Lecture3-4 笔记

news2024/12/25 1:39:25

文章目录

    • 第三讲 所有权:移动与借用&
          • 例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的类型是Option
    self.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.coloradmin.cn/o/2138771.html

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

相关文章

基于Sobel算法的边缘检测设计与实现

1、边缘检测 针对的时灰度图像&#xff0c;顾名思义&#xff0c;检测图像的边缘&#xff0c;是针对图像像素点的一种计算&#xff0c;目的时标识数字图像中灰度变化明显的点&#xff0c;图像的边缘检测&#xff0c;在保留了图像的重要结构信息的同时&#xff0c;剔除了可以认为…

【WPF】桌面程序开发之xaml页面绑定数据模型详解

使用Visual Studio开发工具&#xff0c;我们可以编写在Windows系统上运行的桌面应用程序。其中&#xff0c;WPF&#xff08;Windows Presentation Foundation&#xff09;项目是一种常见的选择。然而&#xff0c;对于初学者来说&#xff0c;WPF项目中xaml页面的布局设计可能是一…

unity3d入门教程七

unity3d入门教程七 17.1物理系统17.2静态刚体17.3刚体的碰撞17.4刚体的反弹18.1运动学刚体18.2碰撞检测18.3碰撞事件回调18.4目标的识别18.5碰撞的规避 17.1物理系统 在物理系统中的物体具有质量和速度的是刚体 不用写代码就会自由落体运动了 17.2静态刚体 给 ‘地面’ 添…

conda安装qgis(亲测没问题)

conda安装qgis&#xff08;亲测没问题&#xff0c;目前测试win10&#xff0c;linux其实也是可以的&#xff09; 目录 1.前提 2.准备条件 3.实战 4.扩展 1.前提 意外发现conda可以安装qgis&#xff0c;即使不是完全版&#xff0c;但是矢量空间分析都可以用&#xff0c;那么…

影刀RPA实战:网页爬虫之CSDN博文作品数据

今天我们使用影刀来采集网页数据&#xff0c;影刀RPA是一款功能强大的自动化办公软件&#xff0c;它可以模拟人工的各种操作&#xff0c;帮助企业自动处理大量重复性、有逻辑规则的工作。影刀RPA在网页数据采集方面表现出色&#xff0c;能够实现对任何桌面软件、Web程序的自动化…

危机中的机遇:客户服务在品牌危机管理中的角色与价值

在瞬息万变的商业环境中&#xff0c;品牌危机如同暗流涌动的漩涡&#xff0c;随时可能将企业卷入深渊。然而&#xff0c;正如古语所云&#xff1a;“祸兮福之所倚”&#xff0c;危机之中往往也蕴藏着转机与机遇。在这一过程中&#xff0c;客户服务作为企业与消费者之间的桥梁&a…

物品识别——基于python语言

目录 1.物品识别 2.模型介绍 3.文件框架 4.代码示例 4.1 camera.py 4.2 interaction.py 4.3 object_detection.py 4.4 main.py 4.5 运行结果 5.总结 1.物品识别 该项目使用Python&#xff0c;OpenCV进行图像捕捉&#xff0c;进行物品识别。我们将使用YOLO&#xff08…

Dating App约会软件都有哪些商业化策略

在设计一个成功的Dating App时&#xff0c;吸引并留住用户&#xff08;特别是女用户&#xff09;和实现商业化是两个核心任务。比如探探、陌陌等&#xff0c;以下是可行的产品流程思路&#xff0c;以及商业化的功能设计策略&#xff0c;借鉴了成熟的约会平台的经验。 吸引并留住…

2000-2021年3月海关数据库

2000-2021年3月海关数据库 1、时间&#xff1a;2000-2021年3月 2、指标&#xff1a;2000-2015数据变量包括&#xff1a;年份、截止日期、进出口分类代码、进出口分类名称、HS商品编码、HS商品名称、金额_美元、数量、价格、经营单位代码、经营单位名称、经营单位地址、电话、…

AI论文写作测评!类似茅茅虫论文写作助手网站

在当前的学术研究和写作环境中&#xff0c;AI论文写作助手成为了许多学者和学生的重要工具。其中&#xff0c;千笔-AIPassPaper和茅茅虫论文写作助手是两款备受关注的平台。本文将对这两款工具进行详细测评&#xff0c;并推荐适合不同需求的用户使用。 千笔-AIPassPaper AI论文…

linux安全软件Hydra使用教程

Hydra 是一个强大的网络登录工具&#xff0c;常用于渗透测试&#xff0c;支持对多种服务和协议&#xff08;如 SSH、FTP、HTTP 等&#xff09;进行暴力crack攻击。它可以通过字典攻击来测试用户名和密码的有效性。以下是关于如何使用 Hydra 的基本步骤和示例&#xff1a; 1. 安…

【mechine learning-九-梯度下降】

梯度下降 更加通用的梯度下降算法算法步骤 上一节讲过&#xff0c;随机的寻找w和b使损失最小不是一种合适的方法&#xff0c;梯度下降算法就是解决解决这个问题的&#xff0c;它不仅可以用于线性回归&#xff0c;还可以用于神经网络等深度学习算法&#xff0c;是目前的通用性算…

【QT】定时器使用

文章目录 关于 Qt 定时器使用的注意细节总结实例-检查工具使用周期时间是否合理UI设计头文件 remind.h源文件 remind.cpp实现效果 关于 Qt 定时器使用的注意细节总结 一、创建与初始化 使用 QTimer 类来创建定时器。可以在构造函数中指定父对象&#xff0c;确保定时器在正确的…

跨境电商代购新纪元:一键解锁全球好物,系统流程全揭秘

添加图片注释&#xff0c;不超过 140 字&#xff08;可选&#xff09; 在全球化日益加深的今天&#xff0c;跨境电商代购成为了连接消费者与世界各地优质商品的桥梁。本文将在CSDN平台上&#xff0c;深入剖析跨境电商代购系统的功能流程&#xff0c;带您一窥其背后的技术奥秘与…

vue3+ant design vue实现可编辑表格弹出气泡弹出窗~

1、这里主要是介绍下::v-deep伪元素的作用。用于穿透组件作用域&#xff0c;以便在组件内部修改样式。用来覆盖Ant Design Vue组件库中的样式 <a-table:dataSource"dataList":columns"columns":scroll"{ x: 100% }":pagination"false&q…

架构师备考的一些思考(四)

前言 对于数学&#xff0c;我们之前学的是对的&#xff0c;但不是真的&#xff0c;所以我们没有数学思维。 对于计算机&#xff0c;我们学校教的是对的&#xff0c;但不是真的&#xff0c;所以仅仅从学校学习知识的应届毕业生&#xff0c;不论985,211&#xff0c;本科&#xff…

优化深度学习模型训练过程:提升PASCAL VOC 2012数据集上Deeplabv3+模型训练效率的策略

创作不易&#xff0c;您的打赏、关注、点赞、收藏和转发是我坚持下去的动力&#xff01; 优化说明&#xff1a; 避免重复下载和解压数据集&#xff1a;将downloadTrue改为downloadFalse&#xff0c;防止每次运行代码都重新下载和解压数据集&#xff0c;从而节省时间。 使用pin…

8. Transforms的使用(三)-- Resize

Transforms的使用(三) 1. 为什么要使用Resize 在模型的训练过程中往往需要图片数据的维度相同,才能适应深度学习模型中的相关神经网络结构,这时候就需要使用Resize保证所有的图片保持相同的尺寸2. 使用Resize调整图片的尺寸 在pytorch2.3的版本上,Resize()支持对Tensor类…

k8s Service 服务

文章目录 一、为什么需要 Service二、Kubernetes 中的服务发现与负载均衡 -- Service三、用例解读1、Service 语法2、创建和查看 Service 四、Headless Service五、集群内访问 Service六、向集群外暴露 Service七、操作示例1、获取集群状态信息2、创建 Service、Deployment3、创…

分贝转换 1 mVpp = 9.03dBmV

分贝转换 1 mVpp 9.03dBmV 函数发生器调节如下参数在频谱仪器上能看到9.03dBmv的电压值函数发生器产生 30mVpp 频谱仪会显示多少dBmV 函数发生器调节如下参数 输出频率&#xff1a;10 MHz 波形类型&#xff1a;正弦波 阻抗&#xff1a;50 Ω 幅度&#xff1a;1 mVpp …