Skip to main content

Smart Pointers

Smart Pointers are references to data, so you can use it, without taking ownership of this data. But before talking about Smart Pointers, lets take a look at normal references.

Normal references

You can create references to variables. This gives code the ability to work with those variables, without taking the ownership.

Reference

TODO

Mutable Reference

TODO

Smart Pointers

Smart Pointers are often required, because they give you additional functionalities, where normal references do not fit the problem. They behave like a pointer, but add safety mechanisms to prevent wrong memory management.

Box

Variables are usually stored in the stack. But sometimes you need to allocate data on the heap memory. A good example is, when the size of the data struct can not be calculated on compile time. The Box smart pointer is basically a pointer to the struct on the heap.

// 5 is allocated in the heap,
// and "Pointer" is a smart pointer
// pointing on "5"
let pointer = Box::new(5);

// To use the value, dereference the pointer
println!("value = {}", *pointer);

// Implicit derefrencing may also work
// because Box implements the Deref trait
println!("value = {}", pointer);

Rc

The ownership of data is always bould to one place. One variable has the responsibility to clean up the memory used when done. but at some points mutiple places need to have ownership of those data.

Rc is a smart pointer with a reference counter, which allows to share ownership on multiple places. Each time another place needs the memory, the Rc pointer is copied and increases the reference counter. And every time the life time of a Rc ends, it decreases the reference counter. Eventually the counter becomes zero and the stored data will be decallocated.

Rc is used to share ownership in single threaded code and provides read only access to the data.

// create a Rc pointer
let magic_number = Rc::new(1337);

{
  // clone the pointer to create multiple references
  // and allow it to be used somewhere
  let magic_clone = Rc::clone(&magic_number);
  // Now the counter is at 2
}
// The lifetime of magic_clone ends and the
// counter is decreased to 1 again

println!("magic number = {}", *magic_number);

Arc

TODO

RefCell

TODO

Cell

TODO

Mutex

TODO

RwLock

TODO

Cow

TODO

Weak

TODO

Pin

TODO