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

【Rust自学】4.5. 切片(Slice)

4.5.0. 写在正文之前

这是第四章的最后一篇文章了,在这里也顺便对这章做一个总结:

所有权、借用和切片的概念确保 Rust 程序在编译时的内存安全。 Rust语言让程序员能够以与其他系统编程语言相同的方式控制内存使用情况,但是当数据所有者超出范围时,让数据所有者自动清理该数据意味着您无需编写和调试额外的代码来获得这个控制权

看完这篇文章,相信你会由衷的感叹Rust所有权机制到底有多么神奇和先进。

喜欢的话别忘了点赞、收藏加关注哦,对接下来的教程有兴趣的可以关注专栏。谢谢喵!(=・ω・=)

4.5.1. 切片的特性

  • 1. 类型和结构

    • 切片类型的表示方式是:&[T]&mut [T],其中 T 是切片中元素的类型。
    • 不可变切片&[T],只允许读取操作。
    • 可变切片&mut [T],允许修改操作。
  • 2. 不拥有数据

    • 切片本质上是对底层数据的引用,因此它不拥有数据。
    • 切片的生命周期与底层数据一致,当底层数据被销毁时,切片也失效。

4.5.2. 字符串切片

以一道题为例:
编写一个函数,它接受字符串作为参数,它返回它在这个字符串中找到的第一个单词,如果函数没找到任何空格,那么整个字符串就被返回。

fn main() {let s = String::from("Hello world");let word_index = first_word(&s);println!("{}", word_index);
}
fn first_word(s:&String) -> usize {let bytes = s.as_bytes();for (i, &item) in bytes.iter().enumerate() {if item == b' ' {return i;} }s.len()
}
  • 因为需要逐个元素地遍历String并检查值是否为空格,所以使用as_bytes方法将String转换为字节数组.
  • 迭代器在以后会讲到,现在只需要知道iter是一个方法,用来逐一获取集合中的每个元素。enumerate是一个工具,它在iter的基础上,为每个元素附加一个索引,并将结果作为元组返回。返回元组的第一个元素是索引,第二个元素是对该元素的引用

程序成功编译,输出是5。也就是Hello后边的空格的索引位置

我们现在有办法找出字符串中第一个单词末尾的索引,但是有一个问题。我们自己返回一个usize ,但它只是&String上下文中的一个有意义的数字。换句话说,因为它是与String不同的值,所以不能保证它在将来仍然有效

比如因为某些原因代码在调用first_word之后写了s.clean();这行来清空s,此时的word_index这个变量就没有意义了;也可以说,Rust编译器发现不了代码使用了s.clean()word_index仍然存在的错误,如果你在之后的代码中还使用了word_index去打印字符,那显然就会发生错误。

这类的API(或者叫函数设计)要求随时关注word_index的有效性,确保这个索引和这个String变量s它们之间的同步性。偏偏这类工作往往相当繁琐而且特别容易出错,所以针对这类问题Rust提供了字符串切片

字符串切片是指向字符串中一部分内容的引用。

在原字符串名前加上&代表对它的引用,在后加上[开始索引..结束索引],表示引用这个字符串的一部分。注意,[]内的区间是左闭右开,所以结束索引是切片终止位的下一个索引值。顺口溜:包左不包右。

fn main() {let s = String::from("hello world");let hello = &s[0..5];let world = &s[6..11];
}

在这个例子中把s从0到5的索引区间(包括0不包括5),也就是"Hello"这部分赋给了hello这个变量;把从6到11的索引区间(包括6不包括11),也就是"world"这个部分赋给了world这个变量
请添加图片描述

由图可见,world这个变量并不会独立于s而存在,这样使得编译器能够在编译过程中就发现许多潜在的问题。

当然,对于索引的写法,还有几种省略的方式:

let hello = &s[0..5];

这个变量是从索引0开始截取的,Rust允许这样的等价写法:

let hello = &s[..5];
let world = &s[6..11];

这个变量截取到了s的最后一个元素,Rust允许这样的等价写法:

let world = &s[6..];

如果想截取整个字符串,那就可以:

let whole = &s[..];

注意事项

  • 字符串切片的范围索引必须发生在有效的utf-8边界内
  • 如果尝试从一个多字节的字符中创建字符串切片,程序会报错并退出

重写代码

学了切片之后,就可以修改文章开头的代码来进一步优化了:

fn main() {let s = String::from("Hello world");let word = first_word(&s);println!("{}", word);
}
fn first_word(s:&String) -> &str {let bytes = s.as_bytes();for (i, &item) in bytes.iter().enumerate() {if item == b' ' {return &s[..i];} }&s[..]
}
  • &str表示字符串切片

这个时候如果在word = first_word(&s);这一行之后加上s.clean();,Rust就能够发现错误并报错:

error[E0502]:cannot borrow `s` as mutable because it is also borrowed as immutable

因为在同一个作用域中出现了可变引用s.clean()和不可变引用&s,违反了借用规则
PS:s.clean()等价于clean(&mut s)

4.5.3. 字符串字面值就是切片

字符串字面值被直接存储在二进制程序之中,在程序运行时会被放入静态内存里

let s = "Hello, World!";

变量s的类型是&str,它是一个指向二进制程序特定位置的切片。&str不可用,所以字符串字面值也是不可变的。

4.5.4. 将字符串切片作为参数传递

fn first_word(s:&String) -> &str {

这是刚刚优化过的代码中声明函数的那一行,这种写法本身完全没有任何问题。但有经验的Rust开发者会使用&str作为s的参数类型,因为这样就可以同时接收String&str类型的参数了:

  • 如果你传入的的值是字符串切片,那么直接调用即可
  • 如果值类型是String,那么可以传入&String类型的实参,当函数参数需要&str而你传递的是&String时,Rust会隐式调用Deref,将&String转换为&str

定义函数时使用字符串切片来代替字符串引用会使APU更加通用,且不会损失任何功能。

根据它,还可以再进一步地优化之前的代码:

fn main() {let s = String::from("Hello world");let word = first_word(&s);println!("{}", word);
}
fn first_word(s:&str) -> &str {let bytes = s.as_bytes();for (i, &item) in bytes.iter().enumerate() {if item == b' ' {return &s[..i];} }&s[..]
}

这行:

let word = first_word(&s);

也可以写成:

let word = first_word(&s[..]);

对于前者,Rust会隐式调用Deref,将&String转换为&str;后者是手动转换为&str类型

4.5.5. 其他类型的切片

fn main() {  let number = [1, 2, 3, 4, 5];  let num = &number[1..3];  println!("{:?}", num);  
}

数组也可以使用切片。num这个切片的本质就是存储了指向number中切片截取的起始点(这个例子中是索引为1的位置)的指针与长度的信息。

其输出是:

[2, 3]

相关文章:

【Rust自学】4.5. 切片(Slice)

4.5.0. 写在正文之前 这是第四章的最后一篇文章了,在这里也顺便对这章做一个总结: 所有权、借用和切片的概念确保 Rust 程序在编译时的内存安全。 Rust语言让程序员能够以与其他系统编程语言相同的方式控制内存使用情况,但是当数据所有者超…...

医学图像 三维重建,原图与灰度图叠加,原图与多图叠加显示;多图像融合显示,彩色灰度图像融合

Part1: Summary 我们在做图像分割或融合时,有时需要显示多份数据进行叠加显示;可能需要这种效果: 四视图: 基于这个,我看一下网上的实现总结了一下;实现了以下几种效果: Part2:多种…...

递归实现指数型枚举(递归)

92. 递归实现指数型枚举 - AcWing题库 每个数有选和不选两种情况 我们把每个数看成每层,可以画出一个递归搜索树 叶子节点就是我们的答案 很容易写出每dfs函数 dfs传入一个u表示层数 当层数大于我们n时,去判断每个数字的选择情况,输出被选…...

Unity实现Root Motion动画的Navigation自动导航

Root motion动画可以将角色的根节点(通常是角色的骨盆或脚部)的运动直接应用到游戏对象上,从而实现角色的自然移动和旋转,避免出现脚底打滑的现象。采用Root motion动画的游戏对象,通常是重载了onAnimatorMove函数&…...

[react]不能将类型“string | undefined”分配给类型“To”。 不能将类型“undefined”分配给类型“To”

场景, 封装组件的时候, 想通过外部传进去一个路由地址, 再用<Link to{}>跳转, 显示这个, 有四种方法解决 第一种 合并运算符 ?? ?? 是 空值合并运算符&#xff08;Nullish Coalescing Operator&#xff09;&#xff0c;它是 JavaScript 和 TypeScript 中的一种逻辑…...

python实现基于RPC协议的接口自动化测试

01 什么是RPC RPC&#xff08;Remote Procedure Call&#xff09;远程过程调用协议是一个用于建立适当框架的协议。从本质上讲&#xff0c;它使一台机器上的程序能够调用另一台机器上的子程序&#xff0c;而不会意识到它是远程的。 RPC 是一种软件通信协议&#xff0c;一个程…...

如何使用PSQL Tool还原pg数据库(sql格式)

新建一个数据库用来还原&#xff1b;选择新建的数据库&#xff0c;右键选择【PSQL Tool】&#xff0c;打开PSQL Tool命令行界面&#xff1b;赋予pg库对sql文件的执行权限&#xff0c;否则会报“Permission denied”的错误&#xff0c;命令如下&#xff1a; chmod urwx D://NoS…...

uni-app商品搜索页面

目录 一:功能概述 二:功能实现 一:功能概述 商品搜索页面,可以根据商品品牌,商品分类,商品价格等信息实现商品搜索和列表展示。 二:功能实现 1:商品搜索数据 <view class="search-map padding-main bg-base"> <view class…...

【深度学习】零基础介绍循环神经网络(RNN)

RNN介绍 零基础介绍语言处理技术基本介绍分词算法词法分析工具文本分类与聚类情感分析 自然语言处理词向量词向量学习模型1. 神经网络语言模型2. CBOW 和 skip-gram3. 层次化softmax方法4. 负采样方法 RNN介绍RNN的变种&#xff1a;LSTM1. Forget Gate2. Input Gate3. Update M…...

青少年编程与数学 02-004 Go语言Web编程 13课题、模板引擎

青少年编程与数学 02-004 Go语言Web编程 13课题、模板引擎 一、模板引擎模板引擎的主要特点包括&#xff1a;模板引擎的应用场景&#xff1a;Go语言中的模板引擎&#xff1a;示例&#xff1a;使用Go的html/template包 二、工作流程1. 创建模板文件2. 准备数据3. 加载模板4. 渲染…...

如何优雅的关闭GoWeb服务器

以下内容均为Let’s Go Further内容节选以及作者本人理解。 这里创建了一个后台进程用于捕获关闭信号&#xff0c;在后台进程中&#xff0c;主要内容为&#xff1a; 创建一个缓冲通道 quit使用signal.Notify函数监听并捕获关机信号SIGINT,SIGTERM&#xff0c;在捕获关机信号后…...

AI程序员,开源的Devin,OpenHands 如何使用HuggingFace Inference API

我用了一下&#xff0c;界面这样子&#xff1a; Github&#xff1a;https://github.com/All-Hands-AI/OpenHands OpenHands 如何使用HuggingFace Inference API huggingface/meta-llama/Llama-3.3-70B-Instruct 而不是 meta-llama/Llama-3.3-70B-Instruct 不要设置base URL&…...

【动手学运动规划】 5.2 数值优化基础:梯度下降法,牛顿法

朕四季常服, 不过八套. — 大明王朝1566 道长 &#x1f3f0;代码及环境配置&#xff1a;请参考 环境配置和代码运行! 上一节我们介绍了数值优化的基本概念, 让大家对最优化问题有了基本的理解. 那么对于一个具体的问题, 我们应该如何求解呢? 这一节我们将介绍几个基本的求解…...

电子应用设计方案66:智能打印机系统设计

智能打印机系统设计 一、引言 随着科技的不断发展&#xff0c;打印机也在向智能化方向演进。智能打印机不仅能够提供高质量的打印服务&#xff0c;还具备便捷的操作、智能的管理和连接功能。 二、系统概述 1. 系统目标 - 实现高效、高质量的打印输出。 - 支持多种连接方式&am…...

iClient3D for Cesium 实现限高分析

作者&#xff1a;gaogy 1、背景 随着地理信息技术的发展&#xff0c;三维地球技术逐渐成为了许多领域中的核心工具&#xff0c;尤其是在城市规划、环境监测、航空航天以及军事领域。三维地图和场景的应用正在帮助人们更加直观地理解空间数据&#xff0c;提供更高效的决策支持。…...

AI开发:使用支持向量机(SVM)进行文本情感分析训练 - Python

支持向量机是AI开发中最常见的一种算法。之前我们已经一起初步了解了它的概念和应用&#xff0c;今天我们用它来进行一次文本情感分析训练。 一、概念温习 支持向量机&#xff08;SVM&#xff09;是一种监督学习算法&#xff0c;广泛用于分类和回归问题。 它的核心思想是通过…...

torch.unsqueeze:灵活调整张量维度的利器

在深度学习框架PyTorch中&#xff0c;张量&#xff08;Tensor&#xff09;是最基本的数据结构&#xff0c;它类似于NumPy中的数组&#xff0c;但可以在GPU上运行。在日常的深度学习编程中&#xff0c;我们经常需要调整张量的维度以适应不同的操作和层。torch.unsqueeze函数就是…...

【WRF教程第3.1期】预处理系统 WPS 详解:以4.5版本为例

预处理系统 WPS 详解&#xff1a;以4.5版本为例 每个 WPS 程序的功能程序1&#xff1a;geogrid程序2&#xff1a;ungrib程序3&#xff1a;metgrid WPS运行&#xff08;Running the WPS&#xff09;步骤1&#xff1a;Define model domains with geogrid步骤2&#xff1a;Extract…...

SD ComfyUI工作流 根据图像生成线稿草图

文章目录 线稿草图生成SD模型Node节点工作流程工作流下载效果展示线稿草图生成 该工作流的设计目标是将输入的图像转换为高质量的线稿风格输出。其主要流程基于 Stable Diffusion 技术,结合文本和图像条件,精确生成符合预期的线条艺术图像。工作流的核心是通过模型的条件设置…...

挑战一个月基本掌握C++(第六天)了解函数,数字,数组,字符串

一 C函数 函数是一组一起执行一个任务的语句。每个 C 程序都至少有一个函数&#xff0c;即主函数 main() &#xff0c;所有简单的程序都可以定义其他额外的函数。 您可以把代码划分到不同的函数中。如何划分代码到不同的函数中是由您来决定的&#xff0c;但在逻辑上&#xff…...

Python爬虫实战:研究MechanicalSoup库相关技术

一、MechanicalSoup 库概述 1.1 库简介 MechanicalSoup 是一个 Python 库,专为自动化交互网站而设计。它结合了 requests 的 HTTP 请求能力和 BeautifulSoup 的 HTML 解析能力,提供了直观的 API,让我们可以像人类用户一样浏览网页、填写表单和提交请求。 1.2 主要功能特点…...

论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(二)

HoST框架核心实现方法详解 - 论文深度解读(第二部分) 《Learning Humanoid Standing-up Control across Diverse Postures》 系列文章: 论文深度解读 + 算法与代码分析(二) 作者机构: 上海AI Lab, 上海交通大学, 香港大学, 浙江大学, 香港中文大学 论文主题: 人形机器人…...

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* …...

【Redis】笔记|第8节|大厂高并发缓存架构实战与优化

缓存架构 代码结构 代码详情 功能点&#xff1a; 多级缓存&#xff0c;先查本地缓存&#xff0c;再查Redis&#xff0c;最后才查数据库热点数据重建逻辑使用分布式锁&#xff0c;二次查询更新缓存采用读写锁提升性能采用Redis的发布订阅机制通知所有实例更新本地缓存适用读多…...

基于IDIG-GAN的小样本电机轴承故障诊断

目录 🔍 核心问题 一、IDIG-GAN模型原理 1. 整体架构 2. 核心创新点 (1) ​梯度归一化(Gradient Normalization)​​ (2) ​判别器梯度间隙正则化(Discriminator Gradient Gap Regularization)​​ (3) ​自注意力机制(Self-Attention)​​ 3. 完整损失函数 二…...

08. C#入门系列【类的基本概念】:开启编程世界的奇妙冒险

C#入门系列【类的基本概念】&#xff1a;开启编程世界的奇妙冒险 嘿&#xff0c;各位编程小白探险家&#xff01;欢迎来到 C# 的奇幻大陆&#xff01;今天咱们要深入探索这片大陆上至关重要的 “建筑”—— 类&#xff01;别害怕&#xff0c;跟着我&#xff0c;保准让你轻松搞…...

C语言中提供的第三方库之哈希表实现

一. 简介 前面一篇文章简单学习了C语言中第三方库&#xff08;uthash库&#xff09;提供对哈希表的操作&#xff0c;文章如下&#xff1a; C语言中提供的第三方库uthash常用接口-CSDN博客 本文简单学习一下第三方库 uthash库对哈希表的操作。 二. uthash库哈希表操作示例 u…...

2025.6.9总结(利与弊)

凡事都有两面性。在大厂上班也不例外。今天找开发定位问题&#xff0c;从一个接口人不断溯源到另一个 接口人。有时候&#xff0c;不知道是谁的责任填。将工作内容分的很细&#xff0c;每个人负责其中的一小块。我清楚的意识到&#xff0c;自己就是个可以随时替换的螺丝钉&…...

react菜单,动态绑定点击事件,菜单分离出去单独的js文件,Ant框架

1、菜单文件treeTop.js // 顶部菜单 import { AppstoreOutlined, SettingOutlined } from ant-design/icons; // 定义菜单项数据 const treeTop [{label: Docker管理,key: 1,icon: <AppstoreOutlined />,url:"/docker/index"},{label: 权限管理,key: 2,icon:…...

CVE-2023-25194源码分析与漏洞复现(Kafka JNDI注入)

漏洞概述 漏洞名称&#xff1a;Apache Kafka Connect JNDI注入导致的远程代码执行漏洞 CVE编号&#xff1a;CVE-2023-25194 CVSS评分&#xff1a;8.8 影响版本&#xff1a;Apache Kafka 2.3.0 - 3.3.2 修复版本&#xff1a;≥ 3.4.0 漏洞类型&#xff1a;反序列化导致的远程代…...