- In the previous section, we saw what happened.
when you pass a non-copy structure,
like employee by value into a function.
The call function receives ownership of the object.
The calling function loses ownership
and can't use the object afterwards.
So it's gone.
That's quite dramatic.
Generally, a better approach
is to pass structures by reference instead.
In that case, the called function borrows the structure,
it becomes a reference, but it doesn't own it.
The calling function retains ownership
and can continue to use the structure afterwards.
So you don't give the object away,
you just let the function borrow the object
but you retain ownership back in your calling function.
That's a much better approach.
So let's have a look at this example.
This function, print_employee,
it receives an immutable reference to an employee.
So we just use the ampersand,
kind of what you'd expect actually.
So you can imagine that e is kinda like a reference
to an Employee object that sits elsewhere
and in that object, it has a name
and a salary and a full-time status like so.
So in order to access the fields in the structure,
well, you can actually use two syntaxes.
And this is really gonna confuse you
if you're a C++ developer
and I was confused by this as well.
So references, it's kind
of like a mixed thing really in Rust.
It looks like a reference
if you're a C++ developer, but really, to be honest,
it behaves more like a pointer actually.
So what you could do
is you could dereference the pointer explicitly to go
to the object that you're referring to.
So go over here.
So star e is effectively like the contents
of the object you pointed to.
And then once you've got there,
you could access a field inside.
So that would be one approach using an explicit reference.
But confusingly, you can also use an implicit reference,
an implicit dereference, like that.
So you can either say star e, or you can just say e.
Effectively, what the compiler does,
when you use a reference,
the compiler knows that e is a reference.
It can quite clearly see that e is a reference.
So it will automatically dereference itself
as if you said star and give you the contents
of the employee.
So this code here, the compiler will effectively convert it
into that code for you.
You can write it either way.
And guess what?
Rust developers tend to write it this way
because it's less noise.
Well, that's the idea of passing
or receiving a reference parameter.
Let's go through the whole kind of workflow.
So let's see what happens from the top.
Here is my higher-level function
and in here, I create an employee object.
So e1 is here
and it's got a name and a salary and a full-time status.
When you wanna pass by reference, or to put it another way,
a function that borrows the employee,
you have to use the ampersand to pass it in by reference.
So this receives a reference to the employee like so
and then as we've seen in my function at the top,
I can either dereference explicitly
or I can dereference implicitly to basically go
to the employee that we're referring to
and to access the fields inside.
So this example is an immutable reference.
I think you can probably imagine what it would look like
if you wanted to have a mutable reference.
You just put the mut, mut keyword everywhere.
So this function receives a mutable reference
to an employee.
Obviously, the employee itself would have to be mutable
in the first place.
And then we can, for example,
give the person a pay rise, I can say dereference
and go to the employee and increase the salary.
That's an explicit dereference using a star,
like contents of
or you can just use an implicit dereference.
And if you use the implicit dereference syntax here,
then the compiler will effectively convert it
into that anyway.
So in reality, you know, people just use this syntax
because it's just simpler to read.
All right, so from the top then,
let's say I've got my high-level function
and in here, I create a mutable employee, e1.
So that has mutable everything.
When you declare a mutable object,
everything inside it is mutable, all the fields are mutable,
the name and the salary and the full-time status.
I then pass a mutable reference.
Remember, when you pass in mutable references,
the ampersand means it's a reference,
meaning you're borrowing, not owning
and it's a mutable reference.
So the mut keyword is needed there
and it's needed here just to make sure
that you are being consistent.
So this function receives a mutable reference like so
and it can change the fields
either using explicit or implicit dereferencing
to access the fields in the object.
So that actually is quite intuitive I think
once you've kind of got the idea.
That seems to be consistent with what you might expect.
So an example, usual project.
The files involved for this part will be mytypes obviously,
which defines the employee structure, the main code,
which declares the module and gets things going.
And the demo file for this part of the demo,
demo _struct_pass by reference,
and then we'll run the application.
So let's take a look at the code and run the application.
Okay, so mytypes, we've seen it before.
There's my employee structure.
Main declares the mytypes module, and it imports,
it declares all the other modules as well for the demo.
And we're currently looking at this piece of code here,
demo_struct_pass_reference.
So let's uncover that statement
and let's have a look at the code.
So I've got two functions plus the kind of driving code
at the top, a function that receives an immutable reference
and a function that receives a mutable reference.
So up here in main,
I've got a mutable employee, Jane, 1,000, true.
Even though the employee is mutable,
it's still possible to pass an immutable reference.
So whilst the object is actually mutable,
this function is like a const function really in C++.
That function, this function here on line 14
treats the employee as const
or immutable, do in the print function.
It just prints but doesn't change.
So it receives an immutable reference.
And I can print out the name
and the salary and the full-time status.
I can either, let me just give myself a bit more space here,
I can either use explicit dereferencing,
give me the contents of the reference, give me the contents
of the object, name, dereference explicitly,
dereference explicitly, or you can do it implicitly,
implicitly dereference e to give me back the structure,
and give me the name and the salary
and the full-time status.
I just wanted to remind you here
that you can either use explicit dereferencing
if you get paid per keystroke,
or you can just use implicit dereferencing,
which is much easier on the eye.
So that was the print function.
And then the reward_employee, it takes a mutable reference
to the employee and it gives the employee
a 500 pound salary increment
using the explicit dereference syntax
and a further 250 pound just to complete the user's good day
using implicit dereference.
So I call that function with a mutable reference.
Oh, and then I print the employee afterwards
with their new salary.
Well, let's run it and see what happens.
Cargo run.
So the initial employee salary using explicit
and implicit dereferencing is 1,000.
And then we reward the employee with a 750 pound pay rise.
And then we print the details again
and you can see that the details have been incremented.
There we go.
So this is the main way
in which you pass structures into a function.
You pass 'em by reference, either immutable if you can,
or mutable if you have to.
So passing objects by reference is the natural way to do it.