为什么Rust编译器允许索引超出范围?

时间:2014-07-22 21:58:06

标签: rust

有人可以解释为什么这会编译:

fn main() {
    let a = vec![1, 2, 3];
    println!("{:?}", a[4]);
}

运行时,我得到了:

  

线程''惊慌失措的索引越界:len是3但索引是4',.. / src / libcollections / vec.rs:1132

3 个答案:

答案 0 :(得分:15)

如果您想通过索引检查访问Vec的元素,可以使用Vec as a slice,然后使用其get method。例如,考虑following code

fn main() {
    let a = vec![1, 2, 3];
    println!("{:?}", a.get(2));
    println!("{:?}", a.get(4));
}

输出:

Some(3)
None

答案 1 :(得分:13)

为了理解这个问题,你必须根据编译器看到的内容来考虑它。

通常情况下,编译器永远不会理解表达式的,只会关于 type 。因此:

  • a的类型为Vec<i32>
  • 4属于未知的整数类型
  • Vec<i32>实现了下标,因此a[4]类型检查

有关的编译器推理并不为人所知,并且有各种方法可以获得它。

  • 您可以允许在编译时评估某些表达式(例如C ++ constexpr
  • 您可以将值编码为类型(C ++非类型模板参数,使用Peano的数字)
  • 您可以使用依赖类型来弥补类型和值之间的差距

Rust现在不支持这些中的任何一个,虽然对前两个有兴趣,但在1.0之前肯定不会这样做。

因此,在运行时检查值,Vec的实现正确地解决(这里失败)。

答案 2 :(得分:-5)

也许您的意思是:

select count(type_id) userCount, type_id as typeId, modified_at as modifiedAt from ...

这将返回一个fn main() { let a = vec![1, 2, 3]; println!("{:?}", a[4]); } ,因此它将返回OptionSome。比较一下:

None

此操作通过引用进行访问,因此它直接访问fn main() { let a = vec![1, 2, 3]; println!("{:?}", &a[4]); } 并导致程序出现恐慌。