- This lesson is all about what happens when you pass things
into a function and then you when you return things
from a function.
The simplest case is when you pass something by value.
So that's what we look at first.
I've got a function, f1.
It takes two parameters, it takes a 32-bit integer
and it takes a string.
Interesting difference between these two parameters.
The i32 type implements copy.
And when you pass by value,
it'll be copied into the function.
String doesn't implement copy.
So when you pass a string value,
you actually move ownership of the string into the function.
It's all to do with the copy trait.
So that's what we're gonna focus on here.
How exactly does the parameter get passed into the function?
So here's my higher level function.
I've declared an integer n and I pass n into here.
What we'll see is that n will just be bit copied
into here and that's easy.
The second parameter is a string.
When you pass a string by value,
it actually moves ownership of the string up to here.
The original function loses ownership of the text
and the receiving function claims ownership of the text.
So you move ownership
into the function and obviously, that has consequences.
So we're gonna look at an example
just to kind of work through that theory.
So what we'll do, first of all, is we'll think
about simple types which implement copy like i32.
When you pass a copyable value,
it is literally just bit copied into the parameter.
The original function still retains ownership
of the original variable.
It's just a copy that gets passed in.
So here's a simple example.
In my high-level function, I've declared n.
N is a simple integer.
So I'll draw it here, 42.
Obviously, when I pass n into the function,
the value of n is bit copied into the parameter.
So iparam comes into being iparam and it's a bit copy.
There's number 42.
It prints out the value.
At the end of the function,
obviously the local iparam is popped off the stack.
It's gone.
Back in the main function, n still owns the variable.
When n was passed in, a copy was passed in
but n continued to kind of own its own data.
So that's fine.
You can still use n after the function has returned.
N still exists and it still owns its own value.
Gets a bit more tricky when you have types
that don't implement copy like string.
So when you pass a non-copy type into a function,
it moves ownership of that value
into the second function.
The original function loses ownership of the text.
It's a move operation.
Effectively, you donate your value into the function.
The function then owns the value.
The original function has lost ownership
and can't be used after the function call.
So it's quite dramatic actually.
Let's see how that actually works.
Right, so in my higher-level function, s is a string
and it has a pointer to, on the heap, it holds some text.
Hello. Like so.
Now, remember, string doesn't implement the copy trait.
So when I assign, effectively pass s by value into here,
sparam, it'll move the value into sparam.
So sparam, if I draw sparam here,
whatever pointer the original string has,
sparam basically points to the same place.
And this original string loses ownership.
Ownership has been moved into the parameter
and the original string s is no longer usable.
We have moved the data away from s.
So inside the function, inside here,
obviously I can use sparam and it'll print out hello.
But of course, the problem is at the end of the function,
this local sparam goes out of scope.
So it it's destroyed, it's drop function is called
and the drop function for sparam will deallocate the buffer.
So it's gone away.
And then when we come back to the original function,
we can't use s anymore.
S is no longer the owner of the text.
When you pass a non-copy type
by value into a function, your variable is basically dead
from then on.
You've given the object away to here.
All right, so obviously, passing objects,
non-copy objects by value has profound consequences.
Once you've passed the value to the function,
you've lost it and the other function now owns it.
So let's have a look at an example.
So for this chapter, we're gonna look
at this project, lesson08_functions.
So here we are in rustdev, lesson08_functions.
Gonna open that project in Visual Studio Code.
Here we are in Visual Studio Code.
In my main file,
I'm going to uncomment the code for the first demo,
demo_passing_values.
Right.
I'm gonna look at how to pass other types
and how to return other types as well later on.
But demo_passing_values.
So I've got an integer and a string.
I pass the integer into the function.
When I pass the integer into the function,
it'll copy the value into here.
We can use the value here, and at the end of the function,
this local variable gets popped off the stack
but n is still usable afterwards, okay?
Because n is a integer, the value is copied
but the original variable, it lives on.
So we can still use n here
but it's different for the string obviously
because with a string, string doesn't implement copy.
So when I pass that by value, it moves ownership
of the text into here and it can use it in here.
But then sparam gets dropped
at the end of the function and the text is gone.
I can't use this object,
I can't use that variable afterwards
because I've moved ownership into here
and it's gone at the end of the function.
I can't use s afterwards.
Let's see what happens if I try to.
I'm gonna get a compile error and do gonna do a cargo check
to see what the error message is gonna be
because it's good to know what the errors are
because you will, you know, these mistakes,
you will make them in your code as well.
So it's good to know what the error message is likely to be.
Oh, I wish I hadn't done it now.
It says, right, well,
in the beginning, you declared this string type.
String doesn't implement the copy trait.
Well, okay, we do know that.
I then moved ownership.
The value of the string was moved at that point.
So s is no longer the owner.
We can't use s afterwards.
So then when we tried to use the string here on line 11,
and get in the error, it says did you want to clone it maybe
so that you didn't lose ownership,
you just kind of copied the text?
Hmm, interesting suggestion.
Maybe that is what I wanted
but certainly it's not working as it stands.
So let me remove that statement.
I can't, having passed my string,
by value into this function,
I can't then use that variable afterwards.
So I've commented that line out.
So that should at least compile now and run.
Okay, so in some_func, iparam is 42
and in some_func, sparam is hello.
At the end of the function, the string was dropped.
We come back up into our main code here, we can use n.
N is still 42, but we can't use the string.
So far what we've seen is if you pass a non-copy type
by value into a function, then you give the object away.
You can't then use that variable afterwards.
What we're gonna look at next
is to overcome this difficulty.
So rather than passing the value and passing ownership,
what you can do instead is pass a reference.
And that's what we're going to look at in the next section.