The second edition of The Rust Programming Language states the following about while loops for iterating over an array:
fn main() {
let a = [10, 20, 30, 40, 50];
let mut index = 0;
while index < 5 {
println!("the value is: {}", a[index]);
index = index + 1;
}
}
[...] It’s also slow, because the compiler adds runtime code to perform the conditional check on every element on every iteration through the loop.
As a more efficient alternative, you can use a for loop and execute some code for each item in a collection.
fn main() {
let a = [10, 20, 30, 40, 50];
for element in a.iter() {
println!("the value is: {}", element);
}
}
In C++ I would expect a compiler/optimizer to produce something with equivalent run-time performance.
Why is this not the case in Rust?
In C++ I would expect a compiler/optimizer to produce something with equivalent run-time performance.
Because the two snippets are not equivalent. The use of a[i]
in Rust maps to a.at(i)
and the use of unsafe { a.get_unchecked(i) }
in Rust maps to a[i]
in C++.
That is, C++ does not perform bounds-checking by default, which is how you get buffer overflows.
Why is this not the case in Rust?
Rust, when not using the unsafe
keyword, should be memory safe. In many situations this is achieved by compile-time checks, but bounds checking require runtime checks in general.
This does not mean that the while
case will always be slower: it just means that you submit yourself to the whims of the optimizer, and sometimes it lets you down (eliminating bounds-checks is a hard problem).
Thus, the recommendation is to use idioms which are known to optimize well.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With