我有一个2D矢量拒绝使用const Button_Selected = Button.extend`
//Small styling change to differentiate between selected and not selected
`;
值进行索引,但如果我使用i32
投射这些值,则会有效:
as usize
编译时,我收到错误消息
#[derive(Clone)]
struct Color;
struct Pixel {
color: Color,
}
fn shooting_star(p: &mut Vec<Vec<Pixel>>, x: i32, y: i32, w: i32, h: i32, c: Color) {
for i in x..=w {
for j in y..=h {
p[i][j].color = c.clone();
}
}
}
fn main() {}
如果我将代码更改为
error[E0277]: the trait bound `i32: std::slice::SliceIndex<[std::vec::Vec<Pixel>]>` is not satisfied
--> src/main.rs:11:13
|
11 | p[i][j].color = c.clone();
| ^^^^ slice indices are of type `usize` or ranges of `usize`
|
= help: the trait `std::slice::SliceIndex<[std::vec::Vec<Pixel>]>` is not implemented for `i32`
= note: required because of the requirements on the impl of `std::ops::Index<i32>` for `std::vec::Vec<std::vec::Vec<Pixel>>`
然后一切正常。然而,这感觉就像是一个非常奇怪的选择,没有理由不被p[i as usize][j as usize].color = c.clone();
类型处理。
在documentation中,有很多例子,例如
Vec
根据我的理解,如果一个没有小数的普通数字默认为assert_eq!(vec[0], 1);
,那么使用i32
索引的原因就没有理由不起作用。
答案 0 :(得分:3)
与Java,C#甚至C ++不同,Rust中的数字文字没有固定类型。文字的数字类型通常由编译器推断,或使用后缀(0usize
,0.0f64
等明确声明)。在这方面,0
中的assert_eq!(vec[0], 1);
字面值的类型推断为usize
,因为Rust允许Vec
按数量进行索引只输入usize
。
至于使用usize
作为索引类型的基本原理:usize
等同于目标体系结构中的 word 。因此,usize
可以指代运行程序的计算机的所有可能存储器位置的索引/地址。因此,向量的最大可能长度是可以包含在isize
(isize::MAX == usize::MAX / 2
)中的最大可能值。对usize
使用Vec
大小和索引可以防止创建和使用大于可用内存本身的向量。
此外,使用足够大的无符号整数来引用所有可能的内存位置允许删除两个动态检查,一个,提供的大小/索引是非负的(如果使用isize
,这个检查必须手动实现),并且两个,创建向量或取消引用向量的值不会导致计算机内存不足。但是,只有当存储在向量中的类型适合一个单词时才能保证后者。