You can’t use any variable until it’s been initialized, regardless of its type. In general, Rust ensures that code can never access any sort of uninitialized value.

Rust has no notation for an uninitialized array.

Rust references are never null. There’s no analogue to C’s NULL or C++’s nullptr. There is no default initial value for a reference and Rust won’t convert integers to references (outside of unsafe code), so you can’t convert zero into a reference. There is simply no way to produce a null reference in safe Rust. Rust tracks the ownership and lifetimes of values, so mistakes like dangling pointers, double frees, and pointer invalidation are ruled out at compile time.

In Rust, if you need a value that is either a reference to something or not, use the type Option<&T>. At the machine level, Rust represents None as a null pointer, and Some(r), where r is a &T value, as the nonzero address, so Option<&T> is just as efficient as a nullable pointer in C or C++, even though it’s safer: its type requires you to check whether it’s None before you can use it.

Rust can eliminate the tag field of Option<T> when the type T is a reference, Box, or other smart pointer type. Since none of those pointer types is allowed to be zero, Rust can represent Option<Box<i32>>, say, as a single machine word: 0 for None and nonzero for Some pointer. This makes such Option types close analogues to C or C++ pointer values that could be null. The difference is that Rust’s type system requires you to check that an Option is Some before you can use its contents. This effectively eliminates null pointer dereferences.

A let declaration can declare a variable without initializing it. The variable can then be initialized with a later assignment:

1
2
3
4
5
6
7
let name;
if user.has_nickname() {
    name = user.nickname();
} else {
    name = generate_unique_name();
    user.register(&name);
}

Rust has the raw pointer types *mut T and *const T. Raw pointers really are just like pointers in C++. Using a raw pointer is unsafe, because Rust makes no effort to track what it points to.

Raw pointers may be null, or they may point to memory that has been freed or that now contains a value of a different type.