Smart Pointers

Smart Pointers in Rust is nothing, but a technique by which we can store the data in the heap instead of allocating them into the stack. The stack will contain only the pointer to the data and the original data will be stored inside the heap.

It may be noted that stack is a data structure that follows the Last-in-first-out principle, where the heap stores everything in the form of a binary tree.

When we assign a variable simply with the help of the keyword let, then the memory allocated for that particular variable is done within a stack. But when the smart pointer is used, the same variable will be stored inside the heap.

To use the smart pointer, we have to use the keyword Box and create a new instance of the pointer.

let value1; Now this variable value1 will be stored in a stack.

let value2 = Box::new(value1); Now this variable value2 is the pointer to the value1 which is now stored in the heap, and not in the stack!

Syntax for Box :

let variable2 = Box::new(variable1);

As shown in the above syntax the variable variable1 is any value which is already assigned data. Now, by default, the variable1 will be stored inside a heap and the variable2 will act as a pointer to that value.

A program to show the use of smart pointer(Allocate a variable into heap).

fn main() {
  let value1 = 5;
  let value2 = Box::new(value1);
  println!("The value which is now stored in heap is = {}", value2);
}

As shown in the above program, 5 is assigned to the variable value1. This value is stored in stack by default. To allocate this variable into a heap, we have declared another variable called value2 which allocates the variable value1 into a heap.

This is done by using the statement: let value2 = Box::new(value1); .

Program Output :

rust-smart-pointer-heap-allocation

Dereferencing a value

Dereferencing a value means accessing a value pointed by another variable. As already mentioned, when a variable is assigned any value, then the value is allocated in stack in Rust, by default. And when we use the Box operator to allocate the variable in Heap, then the actual data are stored in the heap, but the reference value is in the stack.

It can be directly seen that how we can simply declare a variable and assign it a pointer to the heap-allocated variable. The value we get after dereferencing the pointer variable is the actual data.

Steps for dereferencing :

  • Assign a value to a variable: That is simply let the variable store the assigned value into the stack.
  • Use Box : This is to make a heap-allocation for the same variable and create a pointer.
  • Declare another variable: A new variable should be created and the value pointed by the heap pointer, should be assigned into it.

Syntax :

let data = somedata;
let heap_pointer = Box::new(data);
let deref_variable = * heap_pointer;

A program to show the use of dereferencing:

fn main() {
    let my_data = 100;
    let heap_pointer = Box::new(my_data);
    let defref_variable = * heap_pointer;
    println!("The value pointed inside the heap is {}", deref_variable);
}

In the above program, my_data is a simple variable which stores a value 5. (In stack by default.) Next, we have declared a pointer variable called heap_pointer which points the value which is stored in the heap. (Which is done using Box).

Then we have declared another variable to assign it the value which is pointed by the heap_pointer, which is nothing but out actual data.

Program Output :

rust-deferencing

Deref Trait

The deref trait is a method which is inbuilt in the Rust standard library, which is used to implement the deref() method. This method deref() borrows a self and return a reference to an inner data.

A program to show the use of the Deref Trait.

In the below program, we have created a structure called MyMemory which has a generic return type T. Inside the structure, we have a variable called value1 which is of T Type.

struct MyMemory < T > {
  value1: T,
}
use::std::ops::Deref;
impl < T > Deref
for MyMemory < T > {
  type Target = T;
  fn deref( & self) - > & T {
    &self.value1
  }
}
fn main() {
  let value2 = MyMemory {
    value1: 10
  };
  println!("{}", *(value2.deref()));
}

Now, the trait deref is implemented on the structure MyMemory of MyMemory type. The reference of the variable value1 is returned using the deref() method.

Now, in the function main() when we create an instance called value2 of the structure MyMemory, we assign the variable value1 with 10. Now, when we use the method deref() with the variable value2. It will automatically dereference the instance. That is, it will print the data which is pointed by value2, which is value1, i.e 10.

Program Output :

rust-deref-trait

Comment / Suggestion Section
Point our Mistakes and Post Your Suggestions