Rust-数组

数组是一个容器,它在一块连续空间内存中,存储了一系列的同样类型的数据。

数组中元素的占用空间大小必须是编译期确定的。

数组本身所容纳的元素个数也必须是编译期确定的,执行阶段不可变。

如果需要使用变长的容器,可以使用标准库中的Vec/LinkedList等。数组类型的表示方式为T;n

其中T代表元素类型;n代表元素个数;它必须是编译期常量整数;中间用分号隔开。

下面看一个基本的示例:

多维数组

既然T;n是一个合法的类型,那么它的元素T当然也可以是数组类型,因此\[T;m;n]类型自然也是合法类型。示例如下:

数组切片

对数组取借用borrow操作,可以生成一个"数组切片"(Slice)。

数组切片对数组没有"所有权",我们可以把数组切片看作专门用于指向数组的指针,是对数组的另外一个"视图"。

比如,我们有一个数组T;n,它的借用指针的类型就是&T;n

它可以通过编译器内部魔法转换为数组切片类型&T

数组切片实质上还是指针,它不过是在类型系统中丢弃了编译阶段定长数组类型的长度信息,而将此长度信息存储为运行期的值。示例如下:

DST和胖指针

从前面的示例中可以看到,数组切片是指向一个数组的指针,而它比指针又多了一点东西------它不止包含有一个指向数组的指针,切片本身还含带长度信息。

Slice与普通的指针是不同的,它有一个非常形象的名字:胖指针(fat pointer)。

与这个概念相对应的概念是"动态大小类型"(Dynamic Sized Type,DST)。

所谓的DST指的是编译阶段无法确定占用空间大小的类型。为了安全性,指向DST的指针一般是胖指针。

比如:对于不定长数组类型T,有对应的胖指针&T类型;对于不定长字符串str类型,有对应的胖指针αstr类型;以及在后文中会出现的Trait Object;等等。

由于不定长数组类型T在编译阶段是无法判断该类型占用空间的大小的,目前我们不能在栈上声明一个不定长大小数组的变量实例,也不能用它作为函数的参数、返回值。

但是,指向不定长数组的胖指针的大小是确定的,&T类型可以用做变量实例、函数参数、返回值。

通过前面的示例我们可以看到,&T类型占用了两个指针大小的内存空间。

Range

Rust中的Range代表一个"区间",一个"范围",它有内置的语法支持,就是两个小数点...。示例如下:

边界检查

在前面的示例中,我们的"索引"都是一个合法的值,没有超过数组的长度。如果我们给"索引"一个非法的值会怎样呢:

编译通过,执行thread'main'panicked at index out of bounds:the len is 5 but the index is10'。

可以看出,如果用/test10,则会出现数组越界,Rust目前还无法任意索引执行编译阶段边界检查,但是在运行阶段执行了边界检查。下面我们分析一下边界检查背后的故事。

在Rust中,"索引"操作也是一个通用的运算符,是可以自行扩展的。

如果希望某个类型可以执行"索引"读操作,就需要该类型实现std::ops::Index trait,如果希望某个类型可以执行"索引"写操作,就需要该类型实现std::ops::IndexMut trait。

对于数组类型,如果使用usize作为索引类型执行读取操作,实际执行的是标准库中的以下代码:

字符串

字符串是非常重要的常见类型。相比其他很多语言,Rust的字符串显得有点复杂,主要是跟所有权有关。Rust的字符串涉及两种类型,一种是&str,另外一种是string。

&str

str是Rust的内置类型。&str是对str的借用。Rust的字符串内部默认是使用utf-8编码格式的。而内置的char类型是4字节长度的,存储的内容是Unicode Scalar Value。

所以,Rust里面的字符串不能视为char类型的数组,而更接近u8类型的数组。

实际上str类型有一种方法:fn as_ptr(&self)->*const u8。

它内部无须做任何计算,只需做一个强制类型转换即可。

String

接下来讲string类型。它跟&str类型的主要区别是,它有管理内存空间的权力。

关于"所有权"和"借用"的关系,&str类型是对一块字符串区间的借用,它对所指向的内存空间没有所有权,哪怕&mut str也一样。比如:

let greeting:&str ="Hello";

我们没办法扩大greeting所引用的范围,在它后面增加内容。但是string类型可以。示例如下:

相关推荐
用户1563068103514 分钟前
Day01 | Java 基础(Java SE)
java
行者全栈架构师2 小时前
Maven dependency:tree 的 8 个高级用法
java·后端
行者全栈架构师6 小时前
IDEA 中 Maven 项目的 15 个红色报错快速解决方法
java·后端
令人头秃的代码0_06 小时前
mac(m5)平台编译openjdk
java
Rust研习社20 小时前
组合真的优于继承吗?为什么 Rust 和 Go 都拥抱组合舍弃继承?
后端·rust·编程语言
唐青枫1 天前
Java JDBC 实战指南:从 Connection 到事务和连接池
java
一个做软件开发的牛马1 天前
MyBatis-Plus 从零实战:完整搭建可运行 Demo,BaseMapper 零 SQL、Wrapper 条件构造、分页插件与代码生成器详解
java·后端
用户3721574261351 天前
Java 处理 PDF 图片:提取 PDF 中的图片,并压缩 PDF 图片体积
java
用户3721574261351 天前
Java 打印 Word 文档:从基础打印到高级设置
java
用户3521802454752 天前
当 Prompt 学会"热更新":Spring Boot × Nacos3 AI 实战
java·spring boot·ai编程