Pointer, Reference and Ownership in Rust

Tips and Traps¶

References & Pointers

1. You should avoid using lifetime annotation as much as possible especially in public APIs. Leveraging smart pointers is a good approach to elide lifetime annotations. For more discussions on this, please refer to Smart pointers: The secret to write clean Rust code .

Struct std::marker::PhantomData is a zero-sized type used to mark things that "act like" they own a T.

Module std::boxed is a (fat) pointer type for heap allocation. Box<T>, casually referred to as a box, provides the simplest form of heap allocation in Rust. Boxes provide ownership for this allocation, and drop their contents when they go out of scope. Boxes also ensure that they never allocate more than isize::MAX bytes.

Module std::cell is a module providing shareable mutable containers.

Module std::rc is a module providing single-threaded reference-counting pointers. Rc stands for Reference Counted. The type Rc<T> provides shared ownership of a value of type T, allocated in the heap. Invoking clone on Rc produces a new pointer to the same allocation in the heap. When the last Rc pointer to a given allocation is destroyed, the value stored in that allocation (often referred to as "inner value") is also dropped. Shared references in Rust disallow mutation by default, and Rc is no exception: you cannot generally obtain a mutable reference to something inside an Rc. If you need mutability, put a Cell or RefCell inside the Rc.

Struct std::sync::Arc A thread-safe reference-counting pointer. Arc stands for Atomically Reference Counted. The type Arc provides shared ownership of a value of type T, allocated in the heap. Invoking clone on Arc produces a new Arc instance, which points to the same allocation on the heap as the source Arc, while increasing a reference count. When the last Arc pointer to a given allocation is destroyed, the value stored in that allocation (often referred to as cinner value) is also dropped.

Shared references in Rust disallow mutation by default, and Arc is no exception: you cannot generally obtain a mutable reference to something inside an Arc. If you need to mutate through an Arc, use Mutex, RwLock, or one of the Atomic types.

Ownership¶

• Each value in Rust has a variable that's called its owner.
• There can only be one owner at a time.
• When the owner goes out of scope, the value will be dropped.
In [5]:
{
let s1 = String::from("how are you");
let s2 = s1;
println!("{}", s1);
}

    let s2 = s1;
^^
unused variable: s2
help: if this is intentional, prefix it with an underscore

_s2
    let s2 = s1;
^^ value moved here
println!("{}", s1);
^^ value borrowed here after move
let s1 = String::from("how are you");
^^ move occurs because s1 has type String, which does not implement the Copy trait
borrow of moved value: s1

Borrow¶

• Allow infinite borrows for read-only access
• Read-only borrows make the original data immutable
• Only allowed to pass one borrow at a time for write access
In [4]:
{
let mut s1 = String::from("how are you");
let s2 = &s1;
s1.push('?');
println!("{}", s2);
}

    s1.push('?');
^^^^^^^^^^^^ mutable borrow occurs here
let s2 = &s1;
^^^ immutable borrow occurs here
println!("{}", s2);
^^ immutable borrow later used here
cannot borrow s1 as mutable because it is also borrowed as immutable
In [11]:
{
let mut s = String::from("how are you");
println!("{}", &*s);
}

how are you

Out[11]:
()

Move, Copy and Clone¶

Moves, copies and clones in Rust

In [ ]: