老前端学Rust - 第四章(切片)

兄弟们,正反馈越来越差了。。第一章还能有互动的,第二章就开始没有了。怪不到坚持写下去的人那么少。。希望看过的小伙伴能留下足迹~疑问也好吐槽也罢,或者给咱提提建议。

另外扯个闲篇,上次不是说自行车嘛,然后我买了辆自行车,骑了几次,心率上的太快了。。。随便骑骑心率直奔150+。。。前两天骑了20几分钟心率太高就坐着休息了下,结果降到一百零几的时候突然感觉难受,然后心慌难受,心率在没运动的时候直接上到150+,当时感觉人都要没了,浑身发冷、没力气、心慌,第一次感觉离猝死那么近。。。后来打了个车去医院的路上缓下来了就没去。。但是在家平躺都还是120,110,一直到睡到早上才缓过来。。准备挂个心内专家号看看了。兄弟们,真的身体要紧,天天待电脑跟前人要废了。公司是老板的,身体才是自己的。

好了,书接上回,第三章讲到rust最核心也是最基础的概念 - 《所有权》,最后讲到引用这一块,可以通过引用,去在不持有所有权的情况下传递和修改变量等。除了引用,Rust还有另外一种不持有所有权的数据类型 - 切片


切片

切片允许我们引用集合中某一段连续的元素序列,而不是整个集合。

假设我们要获取某个字符串的首个单词作为结果返回,这个函数要怎么写?

e.g.

rust 复制代码
fn first_word(s: &String) -> usize {
    let bytes = s.as_bytes(); // 将s转换为字节数组
    
    // 迭代器
    for (i, &item) in bytes.iter().emumerate() {
        // 判断代表空格的字节
        if item == b' ' {
            return i;
        }
    }
    
    s.len()
}

上面这个函数中有目前我们没学到的迭代器等,不过代码咱肯定看得懂意思,就是先转成字节数组,然后遍历,找到字节为空格的就返回当前位置。

这个函数就是实现了期望功能的函数,它能成功的搜索并返回字符串中第一个单词结尾处的位置索引,如果没有空格就返回字符串长度。但是他有一个问题,他将一个usize独立返回出来,这个usize在脱离s之后就毫无意义。

e.g.

rust 复制代码
fn main() {
    let mut s = String::from("hello world");
    
    let word = first_word(&s);  // 返回5
    
    s.clear(); // 清空当前字符串
}

上面我们调用first_word获取了&s的第一个单词的位置索引,返回5,然后在下一行清空了字符串,由于5这个位置虽然在我们思维上是与s关联的,但是其实并没有真正的有关联,所以这个word其实就失去了任何意义。 所以我们得找一个方案让他们真正有关联。


字符串切片

字符串切片是指向String对象中某个连续部分的引用。

rust 复制代码
let s = String::from("hello world");

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

上面的语法就表示一段连续内存的一个视图,起始位置和结束位置用[]表示(左闭右开),这里额外再讲一点,上面s,hello,world,all这几个都是指向某一个内存地址,其中s, hello, all指向的都是同一块内存地址,而world不是,他指向的是w字节对应的内存地址。

如此,我们就可以重新改造下first_word函数:

rust 复制代码
fn first_word(s: &String) -> &str {
    let bytes = s.as_bytes();
    
    for (i, &item) in bytes.iter().enumerate() {
        if item == b'' {
            return &s[..i];
        }
    }
    
    return [..]
}

字符串字面量就是切片

我们之前使用过的字符串的字面量其实就是一个字符串切片,他是&str类型,指向二进制程序中一个特定位置的切片。

e.g.

rust 复制代码
let s: &str = "hello world";
let s1: &'static str = "hello world";
let s2: String = s1.to_string(); 
let s3: &String = &s2; 
let s4: &str = &s2[..];

有个小细节要提醒下,&'static str这是静态数据区中的字符串的表示方法,表示s1是一个静态数据区中的字符串的切片。字符串字面量默认会存放在静态数据区里,而静态数据区中的字符串总是贯穿程序运行的整个生命期,直到程序结束的时候才会被释放。上面的例子中,s,s1指向静态数据区,s2指向堆内存,s3是s2的引用,指向的也是堆内存,s4是s2的切片引用,指向的也是同一个堆内存地址。

字符串类型String和&str是可以转换的

e.g.

rust 复制代码
let s: String = String::from("hello world");
let s1: &str = s.as_str();
let s2: String = s1.to_string();

其他类型的切片

其实我们first_word中的let bytes = s.as_bytes()这段代码,bytes就是&[u8]类型的切片,表示一个字节串的切片。

rust 复制代码
let a:[i32; 5] = [1,2,3,4,5];
let slice = &a[1..3];

上面这个例子的切片类型就是&[i32],它内部存储了一个指向起始元素的引用及长度。还有其他各种各样的集合会使用切片类型,用泛型的表示法就表示为&[T],T表示任意数组或向量的集合。

OK,本章结束,所有权相关的也就结束了。期望兄弟们动动小手,给点反馈毕竟这种文章本来面向的读者范围就很小了,不像那些面经啥的,随便写写一堆人点赞、评论啥的我还是想跟小伙伴们互动互动,一个人学也很无聊的。。。

相关推荐
小镇程序员12 分钟前
vue2 src_Todolist全局总线事件版本
前端·javascript·vue.js
野槐14 分钟前
前端图像处理(一)
前端
程序猿阿伟21 分钟前
《智能指针频繁创建销毁:程序性能的“隐形杀手”》
java·开发语言·前端
疯狂的沙粒23 分钟前
对 TypeScript 中函数如何更好的理解及使用?与 JavaScript 函数有哪些区别?
前端·javascript·typescript
瑞雨溪31 分钟前
AJAX的基本使用
前端·javascript·ajax
力透键背34 分钟前
display: none和visibility: hidden的区别
开发语言·前端·javascript
程楠楠&M1 小时前
node.js第三方Express 框架
前端·javascript·node.js·express
weiabc1 小时前
学习electron
javascript·学习·electron
盛夏绽放1 小时前
Node.js 和 Socket.IO 实现实时通信
前端·后端·websocket·node.js
想自律的露西西★1 小时前
用el-scrollbar实现滚动条,拖动滚动条可以滚动,但是通过鼠标滑轮却无效
前端·javascript·css·vue.js·elementui·前端框架·html5