In this lecture, we are going to discuss a core concept called ownership.
I consider Rust's to be a reliable language for its memory safety.
We've talked about memory before, but how does rust achieve memory safety?
That's what I want to talk about in this lecture.
We should take the time to understand the underlying features that make rust a memory safe language.
One of the biggest problems in the programming world is memory leaks.
They are a plague to most programmers.
A memory leak is when a program fails to keep track of its data properly.
Let's say we had a variable for storing a number of variables take up memory on the user's machine at
some point.
We're not going to need the variable anymore if we forget to release memory.
We've created a memory leak instead of reusing memory programs will need to reserve additional memory
for additional resources in some languages.
We need to reform the operation of allocating the memory.
However, Ruskin clean memory for us, we don't need to write additional code to benefit from this feature.
This behavior makes rust highly popular among system programmers.
It emphasizes cleaning memory under the hood.
Rust utilizes an ownership model.
Values assigned to a variable are owned by that variable.
It is as simple as that.
Whenever we create a variable, we are creating a new owner.
Rust will automatically allocate memory when a variable is not needed anymore.
In rust lingo, you may hear this process referred to as dropping a value.
This behavior does carry some consequences we should be aware of.
Let's take a look at an example of ownership gone wrong.
We are going to continue working on the same project from the previous lecture.
We have a variable called my account.
This variable has ownership of the value.
The question is when does the value get dropped?
Values are dropped when the function is finished running.
In this example, the main function is to automatically call whenever we run the program once the main
function is finished running.
Russ will release the memory from the variables defined inside of it.
We don't need to make further changes to benefit from this behavior.
Let's say we want to outsource the print line macros into different functions.
We will define two functions for printing the balance and verified fields above the main function define
a function called print balance.
Inside the argument list, let's set an argument called accounts with the type set to bank accounts.
Next, inside the function, we're going to print the balance field, the values inside this macro will
be similar to the print line macro, any main function.
Lastly, let's make a copy of this function.
The logic is going to mainly be the same.
Instead, we're going to print the verified field.
Everything in the second function should be updated to log the verified fields.
Our functions are already inside the main function instead of directly printing these fields.
We will call both functions with the my account variable.
After making those changes will encounter an error.
Take a closer look at the error the compiler is informing us of an ownership error.
It states that the my account variable has been removed.
What exactly does that mean?
As we learned earlier, variables take ownership of a value.
The My Account variable has ownership of the bank account value.
However, we're passing on the my account variable to the print balance function during this process.
Russ gives ownership to the print balance function.
Therefore, the my account variable in the main function has lost ownership by having ownership of the
variable.
The print balance function will be able to access the value stored in the variable after the function
is finished running.
Russ will release memory allocated for the variable.
It's dropping the value, which leads us to our error.
The print verified function wants access to the variable.
At this point, it's been dropped.
Therefore, the print verified function will not be able to print the variable.
The error message should start to make sense.
It's telling us the ownership of a variable has been moved.
We can resolve our issue by using a feature called borrowing.
For example, let's say your neighbor wants to borrow your lawnmower.
The idea of borrowing is to give temporary possession of something you own to someone else.
Assuming your neighbor is trustworthy, they will give back your lawnmower.
This idea of borrowing can apply to programming.
Rust allows us to borrow variables from other functions.
We can modify our functions to borrow the variable rather than taking ownership before the type annotation
in both functions.
We're going to add an ampersand symbol.
By adding this symbol, Russ will prevent the function from taking ownership away and said it'll allow
the function to borrow the value for reading purposes after the function is finished running.
Rust will not drop the value.
Ownership will continue to belong to the my account variable inside the main function.
We're going to add the ampersand symbol to the arguments in both functions.
We're telling Russ to allow these functions to borrow the variables value.
The functions will ask to borrow the value.
The ampersand symbol will need to be added to the argument list and function calls after making those
changes.
The compiler will stop complaining.
Let's try compiling our project.
As expected, we get the same output.
This behavior is very important to understand.
Rust is memory efficient.
By default, it can transfer ownership across functions.
If that's not what you want, you can override behavior by telling the compiler to borrow the value.