【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的类型是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.mfbz.cn/a/876357.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Windows与Linux下 SDL2的第一个窗口程序

Windows效果和Linux效果如下&#xff1a; 下面是代码&#xff1a; #include <stdio.h> #include "SDL.h"int main(int argc, char* argv[]) { // 初始化SDL视频子系统if (SDL_Init(SDL_INIT_VIDEO) ! 0){// 如果初始化失败&#xff0c;打印错误信息printf(&…

火语言RPA流程组件介绍--下拉框选择

&#x1f6a9;【组件功能】&#xff1a;勾选下拉框选项 配置预览 配置说明 丨目标元素 支持T或# 默认FLOW输入项 通过自动捕获工具捕获(选择元素工具使用方法)或手动填写网页元素的css,xpath&#xff0c;指定对应网页元素作为操作目标 丨值 支持T或# 选中目标的值&#xf…

protobuf中c、c++、python使用

文章目录 protobuf实例&#xff1a;例题1&#xff1a;[CISCN 2023 初赛]StrangeTalkBot分析&#xff1a;思路&#xff1a;利用&#xff1a; 例题2&#xff1a;[CISCN 2024]protoverflow分析&#xff1a; protobuf Protocol Buffers&#xff0c;是Google公司开发的一种数据描述语…

嵌入式单片机程序运行基本机理

1. 程序各种要素说明 大家好,今天用一个最简单的程序跟大家讲清楚程序的构成。 1.1. 概述 硬件首先要知道硬件的组成。 在前面章节我们说过,芯片包含Flash和RAM。 他们虽然不是相同的东西,但是都属于同一个地址空间,32位芯片的地址空间大小是4G。 比如ST32,FLASH通常从…

约瑟夫环和一元多项式修正版

这里先附上上一篇博文的链接大家可以对比着看&#xff0c;错误已经改正https://blog.csdn.net/2302_78946488/article/details/141751514?spm1001.2014.3001.5501 约瑟夫环 以下是详细代码 //约瑟夫环 #include<stdio.h> #include<stdlib.h> //建立链表结点 str…

keil 中 printf重定向

int fputc(int ch, FILE *f) {HAL_UART_Transmit(&huart1, (void*)&ch, 1, 1000);return ch;} 同时勾选&#xff0c;使用微库

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

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

炫酷HTML蜘蛛侠登录页面

全篇使用HTML、CSS、JavaScript&#xff0c;建议有过基础的进行阅读。 一、预览图 二、HTML代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-w…

Cubieboard2(五) 安装无线网卡驱动

1 前情提要 1.1 硬件情况 1&#xff09;Cubieboard2&#xff1a;http://cubieboard.org/model/cb2/ Cubieboard2 是一个由珠海的 Cubietech 团队推出&#xff0c;采用全志 A20 处理器的开发板。 手头上的是生产于 2012.9.9 的是 MMC SDCard 而非 dual_card 款&#xff0c;也…

【计算机网络】网络通信中的端口号

文章目录 一、引入端口号二、端口号的作用三、端口号的确定 在TCP/IP协议中&#xff0c;传输层有两个重要的协议&#xff1a;TCP&#xff08;传输控制协议&#xff09;和UDP&#xff08;用户数据报协议&#xff09;。TCP用于提供可靠的数据传输&#xff0c;而UDP则适合用于广播…

打造下一个AI拥抱视频热潮:从CloneAI的成功中汲取灵感

在科技与创意的交汇点,CloneAI以其敏锐的洞察力和高效的执行力,在短时间内迅速崛起,成为App Store的明星应用。其成功不仅在于抓住了AI技术的浪潮,更在于精准地利用了社交媒体的趋势,创造了一个独特的用户体验。对于希望复刻这一成功的开发者们来说,CloneAI的经验无疑是一…

QT多线程编程(基础概念以及示例)

QT多线程编程 前言&#xff1a;基础夯实&#xff1a;一:多线程概述二:QT多线程的使用1. 继承QThread类2. 继承QObject类3. QtConcurrent模块 三:线程同步与通信四:线程安全五:线程管理六:总结 效果展示&#xff1a;实现功能&#xff1a;核心代码&#xff1a;mainwindow.hmythre…

网络穿透:TCP 打洞、UDP 打洞与 UPnP

在现代网络中&#xff0c;很多设备都处于 NAT&#xff08;网络地址转换&#xff09;或防火墙后面&#xff0c;这使得直接访问这些设备变得困难。在这种情况下&#xff0c;网络穿透技术就显得非常重要。本文将介绍三种常用的网络穿透技术&#xff1a;TCP 打洞、UDP 打洞和 UPnP。…

SQL Server数据库简单的事务日志备份恢复

模拟数据库备份恢复过程 1.基础操作 1.创建TestDB数据库&#xff0c;并添加数据 USE [master] GO CREATE DATABASE TestDB CONTAINMENT NONE ON PRIMARY ( NAME NTestDB, FILENAME ND:\TestDB.mdf , SIZE 8192KB , MAXSIZE UNLIMITED, FILEGROWTH 65536KB ) LOG ON ( …

什么是API网关(API Gateway)?

1. 什么是API网关&#xff08;API Gateway&#xff09;&#xff1f; 在微服务体系结构中&#xff0c;客户端可能与多个前端服务进行交互。 API 网关位于客户端与服务之间。 它充当反向代理&#xff0c;将来自客户端的请求路由到服务。 它还可以执行各种横切任务&#xff0c;例…

GHOST重装后DEF盘丢失:深度解析与高效数据恢复方案

在数字信息爆炸的时代&#xff0c;数据安全与恢复成为了每个计算机用户必须面对的重要课题。GHOST作为系统备份与恢复领域的佼佼者&#xff0c;以其快速、便捷的特点赢得了广泛的用户基础。然而&#xff0c;在使用GHOST进行系统重装的过程中&#xff0c;不少用户遭遇了DEF盘&am…

【信创】Linux上图形化多ping工具--gping的编译安装与打包 _ 统信 _ 麒麟 _ 方德

原文链接&#xff1a;【信创】图形化多ping工具gping的编译安装与打包 | 统信 | 麒麟 | 方德 Hello&#xff0c;大家好啊&#xff01;今天给大家带来一篇关于在Linux操作系统上使用gping的文章。gping是一款非常实用的命令行工具&#xff0c;它将传统的ping命令进行了可视化改进…

【大数据方案】智慧大数据平台总体建设方案书(word原件)

第1章 总体说明 1.1 建设背景 1.2 建设目标 1.3 项目建设主要内容 1.4 设计原则 第2章 对项目的理解 2.1 现状分析 2.2 业务需求分析 2.3 功能需求分析 第3章 大数据平台建设方案 3.1 大数据平台总体设计 3.2 大数据平台功能设计 3.3 平台应用 第4章 政策标准保障体系 4.1 政策…

Java设计模式—面向对象设计原则(五) ----->迪米特法则(DP) (完整详解,附有代码+案例)

文章目录 3.5 迪米特法则(DP)3.5.1 概述3.5.2 案例 3.5 迪米特法则(DP) 迪米特法则&#xff1a;Demeter Principle&#xff0c;简称DP 3.5.1 概述 只和你的直接朋友交谈&#xff0c;不跟“陌生人”说话&#xff08;Talk only to your immediate friends and not to stranger…

【开放词汇检测】MM-Grounding-DINO论文翻译

摘要 Grounding-DINO 是一种先进的开放式检测模型&#xff0c;能够处理包括开放词汇检测&#xff08;Open-Vocabulary Detection&#xff0c;OVD&#xff09;、短语定位&#xff08;Phrase Grounding&#xff0c;PG&#xff09;和指代表达理解&#xff08;Referring Expressio…