"unsafe" doesn't turn off any safety features, it just allows you to do additional things which the base language does not, like:
* use raw pointers
* use mutable static globals
* access fields of unions
https://doc.rust-lang.org/book/ch19-01-unsafe-rust.html#unsa...
All the rules of safe Rust still apply inside of unsafe blocks. The borrow checker still works, etc.
v[i] is bounds checked in Rust even in unsafe. The unsafe "super powers" don't include "magically now indexing has no bounds checks" but because Rust's get function v.get_unchecked(i) is marked unsafe‡ you would need to mark code unsafe to use that function and that function doesn't have bounds checks.
If you write:
unsafe {
println!("{}", v[i]);
}
The compiler will point out that unsafe isn't doing anything for you here, v[i] is safe, marking it unsafe is just a waste of everybody's time.C++ doesn't have bounds checked array access for its abandoned built-in arrays, but it does (these days) have bounds checked access for std::array and std::vector as a separate member function, however because they aren't the default few C++ programmers use them even where they undoubtedly should. This is an ergonomics issue, it's just easier to write needlessly unsafe C++.
‡ This said just get() before I edited it, but Steve corrected me, see below.
This is also true in Rust for the same reason, arguably more true since Rust's built-in array type knows how big it is - but the observation in both languages programmers who want indexing write v[i] because that's the natural way to express what you meant, what's different isn't the frequency of need, only the language defaults.
> performance is such that you'd never want that enabled for release.
Let's make sure it's correct before we start worrying about performance
Most devs should learn to use profilers.
> because Rust's get function v.get(i) is marked unsafe
You mean get_unchecked. get is safe, and returns an Option, so that None can be returned if something is out of bounds.
Ways in which it is better:
* A decent package manager
* "Safe by default" (you have to use 'unsafe' to turn off the safety features), unlike C++ which is "unsafe by default" (v[i] is undefined behaviour if i is out of bounds, for all of C arrays, std::arrays and std::vectors).
* Really easy to do multithreading -- I had reached the point with C and C++ where I was of the opinion it is "almost impossible" to write large thread-safe programs, and all communication should be between processes with pipes, wherever reasonable. In Rust I again feel I can safely and productively write multi-threaded code.
The things Rust doesn't let you do (throw pointers around everywhere) can get a little annoying, but I find the extra safety increases my productivity enough that it's worth the tradeoff.