Programming languages differ in how they handle memory and enforce memory management rules. Go and Python employ garbage collectors, so developers can focus on writing code. C and C++ give programmers responsibility for managing memory at a lower level.

Rust treats memory management differently, using concepts it calls ownership and borrowing. It uses a “borrow checker” to enforce memory safety efficiently.

What Is Ownership?

Ownership is a feature and convention of Rust that helps ensure the memory safety of programs without a garbage collector. It’s another way of tackling the problem of memory leaks in your code.

The Rust compiler checks if a program obeys the ownership rules at compile time. If the program follows these rules, it can run. If it doesn’t, the compiler refuses to produce an executable.

Rust verifies the ownership rules using the borrow checker. The borrow checker verifies the ownership model and decides if a value in memory (stack or heap) is out of scope or not. If a value is out of its scope, it’s not accessible to other parts of the program unless it’s borrowed.

The Ownership Rules

In Rust, every variable owns the value it’s initialized with, and there can only be one owner. Once the owner is out of scope, the value is dropped. It’s important to understand the details of the ownership rules.

The first ownership rule is that every variable owns its initialized value.

        let owner = String::from("one");

The owner variable above owns the string one and, unlike languages such as Python and Go, that value will be dropped on variable reassignment.

The second ownership rule is that two variables cannot point to the same memory location; every value can have only one owner.

        let new_owner = owner;

The new_owner variable now owns the value stored at the memory location of the owner variable. If you try to use the owner variable, the compiler will panic, and it will refuse to generate an executable.

result of using a dropped variable

In most languages that use garbage collectors, two variables can point to the same memory location. Here’s an example of equivalent JavaScript code:

        let owner = "owner";
let new_owner = owner;
console.log(new_owner);

Running the JavaScript code above works with no errors, and if you do the same in Go or Python, your program will work without errors too.

The third ownership rule is that once a variable is out of the declared scope, the value gets dropped, and memory is deallocated.

        // a variable in a separate scope
{
    let example = String::from("Here's a new scope");
}
 
print!("{}", example)

You cannot access the example variable outside its scope; trying to do so will cause the compiler to panic.

result of using a variable out of its scope

Ownership in Functions

When you pass a value to a function as an argument, the function can access that variable even though it wasn’t declared in its scope:

        fn printer(value: String) -> String {
    return value
}
 
fn main() {
    let x = String::from("Prints a value"); // x owns the string value
 
    // ownership is moved to the printer function here
    print!("{} The Result of Printing X is that it -:", printer(x));
}

The function can access that variable because Rust moves ownership of it to the function at compile time.

You might think it’s still possible to use the variable later in its original scope:

        fn printer(value: String) -> String {
    return value
}
 
fn main() {
    let x = String::from("Prints a value");
    print!("{} The Result of Printing x is that it -:", printer(x));
 
    // Trying to use the variable after ownership of its value has been transferred
    println!("{} shouldn't be accessible", x)
}

But if you try this, the compiler will panic and refuse to produce an executable:

result of using a variable after it has been moved (1)

Rust Prioritizes Code Reusability

Code reusability is an essential practice, but to practice code reusability you need to understand Rust’s ownership rules.

Rust is a very flexible programming language. It provides concepts like borrowing, moving, copying, and cloning ownership for variable reusability.