Slice 类型
slice 允许你引用集合中一段连续的元素序列, 而不用引用整个集合, slice 是一种引用, 所以它没有所有权
用c语言操作内存模拟实现 Rust 切片, 从而看清 Slice(切片) 的本质:
c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// 定义一个结构体来模拟 Rust 的切片
typedef struct Slice {
char *source_data_ptr; // 保存原数据内存地址的指针(切片的开始位置)
size_t length; // 切片数据的长度
} Slice;
// 创建源数据内容, 创建一个字符串切片
Slice create_slice(char *array, size_t start, size_t end) {
Slice slice = {
.source_data_ptr = array + start,
.length = end - start,
};
return slice;
}
// 打印切片的内容
void print_slice(const Slice *slice) {
for (int i = 0; i < slice->length; i++) {
printf("index:%d, value:%c \n", i, slice->source_data_ptr[i]);
}
}
int main() {
// 创建一个字符串, 存放到堆中, 模拟不确定字符串长度的情况
int str_len = 11;
char *str = (char *)malloc(sizeof(char) * str_len + 1); // +1:最后有个 \0 字符
if (str == NULL) {
fprintf(stderr, "Memory allocation failed at %s:%d\n", __FILE__, __LINE__);
return 1;
}
strcpy(str, "hello world");
// 创建一个切片, 从索引 6 开始到 11 结束
// 为什么切片没有所有权, 因为它存的不是原字符串, 而是
// "部分字符串的描述": 源数据的内存地址(切片开始位置), 切片数据长度
// 获取的时候, 根据切片的描述去源数据中获取
Slice slice = create_slice(str, 6, str_len);
// 打印切片的内容
print_slice(&slice); // world
// 最后释放原字符串的内存
free(str);
str = NULL;
return 0;
}
字符串 slice
rust
fn main() {
let string = String::from("hello world");
let str = &string[6..11]; // 表示 6-11
// 这个语法中的开始和结尾是可以省略的
let str1 = &string[...5]; // 表示 0-5
let str2 = &string[6...]; // 表示 6 到最后
let str3 = &stirng[..]; // 表示最前到最后
println!("str: {str}");
println!("str1: {str1}");
println!("str2: {str2}");
println!("str3: {str3}");
}
字符串字面值就是 slice
rust
fn main() {
// 注意这俩的区别
let str: &str = "hello";
let string: String = String::from("world");
println!("str: {str}");
println!("string: {string}");
}
slice 作为函数参数和返回值
rust
fn first_world(str: &str) -> &str {
// 将字符串/切片转字符数组 ['h', 'e', 'l', 'l', 'o']
let bytes = str.as_bytes();
for (i, &item) in bytes.iter().enumerate() {
if item == b' ' {
return &str[0..i];
}
}
// &str[..] 可能会有警告, 所以建议修改为这样
&str[0..bytes.len()]
}
fn main() {
let str = String::from("hello world");
// &str 是 &String, 但是可以看做 &str[..]
// 这样就可以同时兼容 &String 和 &str 类型
let sub_str = first_world(&str);
println!("sub_str: {sub_str}");
}
其他类型的slice
rust
fn main() {
let arr = [1,2,3,4,5];
let sub_arr = &arr[0..3];
let mut i = 0;
while i < sub_arr.len() {
println!("i={}", sub_arr[i]);
i += 1;
}
}