🦀 Rust 数组、向量和切片快问快答

测试你对Rust集合类型的理解程度

10
题目数量
18
预计时间(分钟)
⭐⭐⭐
难度等级
第1题 (判断题)
在Rust中,数组的长度是固定的,而向量(Vec)的长度是可变的。
正确
错误

答案解析:

答案:正确

数组([T; N])的长度在编译时确定,是类型的一部分,不能改变。

向量(Vec<T>)是动态数组,可以在运行时增加或删除元素。

例如:[i32; 5]是固定长度的数组,Vec<i32>是可变长度的向量。

第2题 (选择题)
下列哪种方式可以创建一个包含5个元素,每个元素都是0的数组?
[0; 5]
[0, 0, 0, 0, 0]
vec![0; 5]
以上都可以

答案解析:

答案:[0; 5]

[0; 5]是创建数组的语法,表示5个元素都是0的数组。

[0, 0, 0, 0, 0]也能创建相同的数组,但比较冗长。

vec![0; 5]创建的是向量,不是数组。

虽然后两种方式在某些情况下可行,但题目问的是最直接的方式。

第3题 (选择题)
切片(&[T])和数组([T; N])的主要区别是什么?
切片存储在堆上,数组存储在栈上
切片长度在运行时确定,数组长度在编译时确定
切片可变,数组不可变
切片只能包含引用,数组包含实际值

答案解析:

答案:切片长度在运行时确定,数组长度在编译时确定

切片(&[T])是对连续内存区域的引用,长度在运行时确定。

数组([T; N])的长度N是编译时常量,是类型的一部分。

切片本身是一个胖指针,包含指向数据的指针和长度信息。

数组和切片都可以是可变的或不可变的,取决于声明方式。

第4题 (判断题)
Vec<T>在内存中总是连续存储的,就像数组一样。
正确
错误

答案解析:

答案:正确

Vec<T>确实在内存中连续存储元素,这保证了良好的缓存局部性。

Vec<T>内部使用一个指向堆内存的指针、容量和长度来管理数据。

这种连续存储使得Vec<T>可以高效地转换为切片(&[T])。

当容量不足时,Vec会重新分配更大的连续内存块。

第5题 (选择题)
以下代码的输出是什么?
let arr = [1, 2, 3, 4, 5]; let slice = &arr[1..4]; println!("{}", slice.len());
2
3
4
5

答案解析:

答案:3

&arr[1..4]创建一个从索引1到3(不包括4)的切片。

包含的元素是:arr[1] = 2, arr[2] = 3, arr[3] = 4。

所以切片长度是3。

范围语法[start..end)是左闭右开区间。

第6题 (选择题)
下列哪个方法可以向Vec<T>的末尾添加元素?
push()
append()
insert()
add()

答案解析:

答案:push()

push()方法将元素添加到向量的末尾。

append()方法将另一个向量的所有元素移动到当前向量末尾。

insert()方法在指定位置插入元素。

Rust中没有add()方法用于向量操作。

第7题 (判断题)
可以直接比较两个不同长度的数组类型,例如[i32; 3]和[i32; 5]。
正确
错误

答案解析:

答案:错误

[i32; 3]和[i32; 5]是不同的类型,不能直接比较。

数组的长度是类型的一部分,不同长度的数组是不同类型。

如果要比较内容,需要先转换为切片:&arr1[..] == &arr2[..]。

或者使用as_slice()方法转换后再比较。

第8题 (简答题)
Vec<T>的capacity()和len()方法有什么区别?

答案解析:

答案:capacity()返回容量,len()返回长度

len()返回向量中实际存储的元素数量。

capacity()返回向量在不重新分配内存的情况下可以存储的元素数量。

capacity >= len,当len达到capacity时,push新元素会触发内存重新分配。

可以使用with_capacity()或reserve()来预分配容量,避免频繁重新分配。

第9题 (选择题)
以下哪种切片语法是正确的?
&arr[..3]
&arr[2..]
&arr[1..4]
以上都正确

答案解析:

答案:以上都正确

&arr[..3] - 从开始到索引2(不包括3)

&arr[2..] - 从索引2到结尾

&arr[1..4] - 从索引1到索引3(不包括4)

还有&arr[..]表示整个数组的切片。

第10题 (简答题)
什么是"胖指针"(fat pointer)?在Rust的切片中如何体现?

答案解析:

答案:包含指针和长度信息的指针

胖指针是包含额外元数据的指针,不只是内存地址。

切片(&[T])是胖指针,包含:

1. 指向数据起始位置的指针

2. 切片的长度信息

这使得切片可以安全地知道自己的边界,防止越界访问。

相比之下,普通指针(*const T)只包含内存地址。

🎉
恭喜完成测验!
10/10
你对Rust集合类型的掌握非常出色!