【发布时间】:2015-04-07 23:43:20
【问题描述】:
如果你尝试使用不在数组中的下标,你会得到一个错误:数组访问是在运行时进行边界检查的。
为什么 Rust 在运行时检查数组边界,而大多数其他检查似乎发生在编译时?
【问题讨论】:
标签: arrays compiler-errors runtime-error rust language-design
如果你尝试使用不在数组中的下标,你会得到一个错误:数组访问是在运行时进行边界检查的。
为什么 Rust 在运行时检查数组边界,而大多数其他检查似乎发生在编译时?
【问题讨论】:
标签: arrays compiler-errors runtime-error rust language-design
因为在一般情况下在编译时检查索引是不可行的。即使对于小程序,推理任意变量的可能值也是困难和不可能的。没有人愿意:
...每个切片/Vec/等。访问,因为这是在编译时执行边界检查所必须做的。您基本上需要依赖类型。
除了可能使类型检查无法确定(并使程序的类型检查变得更加困难)之外,类型推断通常变得不可能(并且在最好的情况下受到更多限制),类型变得更加复杂和冗长,并且复杂性语言显着增加。只有在非常简单的情况下,无需大量额外的程序员工作就可以证明索引在界限内。
此外,摆脱边界检查的动机很小。生命周期通过几乎完全消除垃圾收集的需要来减轻负担——这是一个巨大的侵入性功能,具有不可预测的吞吐量、空间和延迟影响。另一方面,运行时边界检查非常无创,开销很小且众所周知,并且即使整个程序的其余部分都大量使用它,也可以在性能关键部分选择性地关闭它。
请注意,编译器可以对数组的越界访问做一些简单的检查:
let a = [1, 2];
let element = a[100];
error: index out of bounds: the len is 2 but the index is 100
--> src/main.rs:3:19
|
3 | let element = a[100];
| ^^^^^^
|
= note: #[deny(const_err)] on by default
但是,这是有限的,并且可以通过使索引值不是“显而易见的”常量来轻松避免:
let a = [1, 2];
let idx = 100;
let element = a[idx];
【讨论】: