Open In App

Rust – Concept of Ownership

Improve
Improve
Like Article
Like
Save
Share
Report

Rust programming language is known for its memory management. This article explains how Rust uses its Ownership model for better memory management. If you want to have a recap of Rust syntax before getting on this article you can refer to the Rust Archives.

Generally, there are 2 ways to manage memory in a program by using either Garbage Collects (or) programmer has to explicitly define the memory usage. Both the options have their advantages and disadvantages like explicit managing being faster but Garbage collection being easier to implement. Rust follows a new approach called “Ownership” which promises to be faster and will be easier when you get used to it.  The ownership model is new for programmers but when you understand and start practicing you can get better at using it.

What is Memory Safety?

Memory safety is the property of a program where memory pointers always used to point to valid memory of the correct type and size. A memory unsafe program may crash or produce unexpected output and errors. It also may cause data leaks which in turn reducing the security of the program. One of the examples that can cause memory safety issues is Dangling pointers(pointers that point to invalid data (or) null).

Stack and Heap

Rust stores primitive datatypes directly into the memory but complex datatypes are generally stored in either Stack (or) Heap.

Stack stores variables of size at compile time. A stack follows a last in first out order. All scalar types can be stored in the stack as the size is fixed. If the size of the variable is unknown at compile time then they are stored in a heap which is suitable for dynamic datatypes. Heap is allocated used to store variables that may change throughout the life cycle of the program. Performing operations on a stack are faster than heap because of fixed size and direct access.

Rust Ownership Rules

Rust ownership rules are the guidelines (or) standards for the Ownership model. These are

  • Each value in Rust has a variable called its owner.
  • There can only be one owner at a time.
  • When the owner goes out of scope, the value will be dropped.

Here is a simple Rust program following the above rules

Rust




fn main() {
    print_gfg()
}
 
// gfg is not declared
fn print_gfg(){
   
   //gfg declared and its validity starts
    let gfg = "GeeksForGeeks"
   
    // gfg is in scope so valid
    println!("{}",gfg);
}


Output:

GeekdForGeeks

Let us look into the program once. The main function has only one line calling print_gfg() function. The print_gfg() function prints out the string “GeeksForGeeks”.  We used the variable “gfg” to store the string “GeeksForGeeks”, so gfg will become the string, and as it is declared in print_gfg() function the scope of the variable where it is the owner and valid is till the end of the function.

Rust ownership

Multiple Variables and Data

In the above program, we have seen how a variable can access data, Now we will see an example of how multiple interacts with the same data.

Rust




fn main() {
    print_gfg()
}
 
// gfg is not declared
fn print_gfg(){
   
    //gfg declared and its validity starts
    let gfg = "Geeks";
   
    // gfg1 copies the data in variable gfg
    let gfg1 = gfg;    
   
    // gfg, gfg1 are in scope so valid
    println!("{} For {}",gfg, gfg1);
} //gfg, gfg1 both go out of scope


 
In this Program, the variable gfg1 copies data in variable gfg but is valid because size of the variable is known before compile time, so Rust stores the variable in stack.

program valid

Now lets us look at a program where data is stored in heap and try to copy that data to another variable 

Rust




fn main() {
    print_gfg()
}
 
fn print_gfg(){
    let gfg = String::from("Geeks"); 
    let gfg1 = gfg;
    println!("{} For {}",gfg, gfg1);
}


This gives an error because the size of gfg variable is unknown at compile-time and when we refer gfg1 to gfg the pointer moves from gfg to gfg1 rather than copying. To make it copy the data rather than moving it when need to use the clone method 

Rust




fn main() {
    print_gfg()
}
 
fn print_gfg(){
    let gfg = String::from("Geeks"); 
    let gfg1 = gfg.clone();
    println!("{} For {}",gfg, gfg1);
}



clone

You can learn more about how Rust handles multiple data variables from References and Borrowing

 



Last Updated : 06 Oct, 2022
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads