In this video, we'll see how we can do pass-by-reference
using pointer parameters.
In c++, we can use pointers and the de-reference operator
to achieve pass-by-reference.
In this case, the function parameter is a pointer, and the actual
parameter can be a pointer variable or the address of a variable.
Let's see what this looks like syntactically.
Here we're declaring a function prototype and
then defining the function.
The function is called double data.
And it expects a pointer to an integer as a parameter.
Notice it doesn't return anything.
Instead, it will double the contents of the data the pointer points to.
So in the body of the function, we simply de-reference the pointer
and multiply the value points 2 by 2, and assign it right back.
I've written this using a compound assignment statement, but I've also
written out the long form of the assignment statement just in case
the compound assignment is confusing.
I also chose to multiply by 2 on purpose since this uses the asterisk
as the multiplication operator.
Keep them straight, don't let the syntax confuse you.
In one case, the asterisk is multiplication, and in the other, it's
indirection or de-reference operator.
Okay, so how do you call this function.
Let's see that in the next slide.
We know that since the function parameter is a pointer to an
integer, that means it expects the address of an integer.
Well, in this case, I have an integer named value and
it's initialized to 10.
I can call double data with the address of that integer
using the ampersand, which is the address of operator.
When I return from the function, I now display value which has doubled to 20.
Let's head over to the IDE and see this and other examples of
pass-by-reference with pointers.
Okay, so I'm in the IDE.
And you can see that I'm in the section 12 workspace in
the passing pointers 1 project.
We'll go over a couple of different projects that do pass-by-reference
using pointers a little bit differently from one another.
So you can see exactly what's happening, and I'll walk
you through these in detail.
You can see here that we've got the same function that we wrote in the
slides, right here, double data.
It expects a pointer to an integer.
And all it does is it doubles whatever it's pointing to, right.
So whatever integer is pointing, it was just doubling it.
And here's my main, which we're going to run.
We're going to run main couple different ways.
First, this part right here, and then the second part right here.
This, you'll see is use the address of a value, and this is using an actual
pointer, so it's two different ways to pass really the same information in.
Okay, so let's start running this.
We've got our main, and it's activated on the stack, right here.
You'll notice main has two local variables.
It's got an integer value, and it's got an integer pointer.
So the value is on the stack.
And right now, it's initialized to 10.
And we also have an int pointer, which is a pointer to an integer.
And right now, it's null and.
I'll just leave it blank.
Let's say that value is in address 1000.
And in pointer is that address 2000, just to keep things straight.
Okay, so that's where we're at.
Now we're here at line 16, output value.
Well, what's value?
Well, we just go to the variable and grab with its contents, right.
So we're going to display a 10 here, just like we have before.
Now we call the function double data, and we pass in the address of value.
Okay, so main stops what it's doing, and we transfer control
over to this function up here.
So we're going to call double data, and we're going to
pass in the address of value.
You can see right here, what's the address of value, it's a 1000.
So we're gonna pass in a 1000 to this function.
Okay, that 1000 will get copied into end pointer.
So that function right here has a local variable, called int pointer.
And you can see that guy right there.
Notice it's the same name as this variable.
That's okay, we can use the same name for different variables.
These are two different variables and two different scopes.
Okay, so we're passing in a 1000 to it.
So that's what we're doing.
There's our pointer.
So now that int pointer is pointing to this value,
right here at address 1000.
So what do we do now?
Well, we're going to double that value basically.
So let me write this out longhand here, so we'll de-reference int
pointer on the left-hand side equals again the reference int
pointer times 2, and that's what this compound assignment is doing.
Notice that, that asterisk right there is multiplication.
These asterisks here, that's the the reference operator.
Keep them straight. It doesn't matter that you're asked, just look at the context,
and it should be pretty clear.
All right, so let's execute this.
De-reference in pointer follow the point to where it's pointing,
right here I got a 10, multiply that by 2, gives me the 20.
And we're assigning 20 into wherever int pointer is pointing.
Well, int pointer is pointing to a 1000.
So we just change that 10 to a 20.
Okay, at this point, that function is done, so we're
going to clean up the stack.
This activation gets popped off the stack, so this is all gone now.
There you go.
Now we're back to main.
And we output the value.
The value is now 20, and we're done with that function call.
Okay, so now let's keep going.
We're here now.
We're going to output a bunch of lines.
And then we're setting int pointer to the address of value.
Well, int pointer was null before.
Remember, we nulled it out right here.
So at this point, int pointer now is the address of value.
What's the address of value?
It's a 1000.
So it's a 1000.
There's my pointer.
I'm pointing to value so.
What do I do now?
I call double data again.
So let's call double data.
And what are we passing into it this time?
Int pointer.
Well, what's the value of int pointer?
A 1000.
So we're calling this with a 1000, which is the address of some integer.
So we activate that on the that activation record, and
it's got that same local variable, right, int pointer.
That's this guy right up here, and we're copying a 1000 in.
There's the pointer, same as we had before.
So what do we do now?
We execute this code.
It now changes this 20 to a 40.
Okay, when the function is done, we clean up our stack, we pop that
activation record off the stack.
So this pointer is gone.
And then we come right back to main, and we say output to value.
Well, the value is now 40.
Okay, so there you go.
This is how pass-by-reference with pointers works.
It's really pretty straightforward.
Let's execute this code now, and you'll see the result is -- and I'll
slide this over just a little bit, you can see value here was 10, then
we doubled it to 20, then we called it again and doubled it again to 40.
All right, perfect.
So let's take a look at another example now.
Okay, so here's another example.
I'm in the same workspace, section 12.
Now I'm in the passingPointers2 project.
And what I've done here is I've written a swap function, that
basically swaps 2 variables, 2 integer variables in this case.
And here's my main that exercises it.
So let's let's try this out.
Here's my main.
As usual, here's the stack.
Main has 2 local variables.
It's got x and it's got y.
X is initialized to 100, and y is initialized to 200.
Let's assume that desired address is 1000 and 2000.
So we've got some nice easy numbers to work with.
Okay, so right here, we're outputting what's x?
We're putting a new line in front of x, but that's okay.
What's x?
Well, x is 100.
So we're going to display 100 here.
And now we're going to say, well, what's y?
We're going to output the value of y which is 200, pretty easy.
Now main stops what it's doing, and we transfer control over to swap.
Okay, so we're going to call swap.
And you'll notice swap has 3 local variables.
It's got an a, it's got a b, and it's got a temp.
So we need to allocate storage for all of those on the activation
record on the stack, right.
So we've got a, we've got b, and we've got temp.
In this case, a and b are both pointers to integers and temp
is just a regular integer.
Okay, so we're going to call swap with the address of x and the address of y.
The address of x is a 1000, and the address of y is 2000.
So that's what the call looks like, right.
Now this x, right here, right, gets mapped to that parameter
a, so that's what we're doing.
We're copying that value to a.
So a is now going to be.
What x is right here, right.
So a is going to get a 1000, and b will get 2000.
So here are your pointers.
B is pointing right here, and a is pointing right there.
All right, so now let's start executing this code.
Temp, we're assigning what a points to, to temp.
Well, what is a point to?
We know it points to an integer, right, because
this is an integer pointer.
So we're gonna take the integer that a points to.
Let's follow a, it points to a 100.
And we're storing it in temp.
Temp is an integer, not a pointer.
Okay, so that's done.
Now we're going to execute the second one which says,
take what b is pointing to.
All right, let's follow b.
B is pointing to 200, and put it into where a was pointing.
Okay, a was pointing here.
So we're going to put the 200 here.
So that's done.
And then we'll take the temp, which was 100 right here.
And we're going to put it into where b was pointing.
So b was pointing to here.
So we're going to put the 100 here.
Notice those two integers got swapped now.
Okay, so at this point, the function's done.
What do we do?
We clean up the stack, we pop off that activation record.
All this is now gone.
And we just clean these up as well.
And that's where we're at right now.
So we're back in main now.
What's x?
We print out, the value of x is 200.
And we display the value of y right here, which is 100.
Notice that we actually swapped those variables.
Okay, so that's really what's going on with pass-by-reference
with pointers in this example.
It's pretty straightforward.
If you remember, we did this with references.
References is probably what you'd want to do here.
But I'll talk about using references versus pointers in the very last
video in this section, that gives you some insight as to what to use when.
But there you go.
This is how you do it with pointers.
Let's look at another example now.
Okay, so I've switched over to the PassingPointers3 project
in the section 12 workspace.
In this case, we're going to pass a pointer to a vector rather than using
integers as we've done in the past.
And there's a couple of examples in this main, and I'll leave the
second example here that's commented out for after I do this one.
So this is what I've got.
I've got a real simple function here called display, and it expects
a pointer to a vector of string.
So it expects the address of some vector that holds strings.
Okay, And all it's doing is just looping through the vector and
printing out all the strings in it.
I'm not going to draw the stack out now.
I think this is going to be pretty easy to follow now that.
I've done over all those examples.
So in this case, I've got a vector of string objects.
It's called stooges, and here's the 3 stooges: larry Moe and Curly.
So what have I got, I've basically got a vector object.
And it's got 3 strings: Larry Moe and Curly.
It's called stooges, and it exists at location 1000 on the
stack there, okay, in the main in mains activation record.
Then I'm just calling stooges here.
I'm calling display, and I'm passing in the address of stooges.
Perfect.
So now once I'm here in this display function that you see here
on line 7, once I'm here, all I want to do is display all those
strings that are in the vector.
So I'm going to use a range base for loop that just iterates through the
vector and prints out the strings.
Well, I have a pointer.
Here's my v, right.
And v has a 1000 in it.
So this is v, right here, it's pointing.
V is not the vector again.
V is just a simple pointer.
So in order to get to what the pointer is pointing to,
I de-reference the pointer.
That's what I need to do.
So if I de-reference v, I've got this stooges vector right here.
And that's what's going on right there.
So for auto, which is a string, right.
So for every string in the collection.
Well, the collection is not v, these the pointer to the collection.
So if I de-reference v, I get the collection.
And this executes just like you would expect.
Okay, now let me clear this out, and I'll run it real
quick so that we can test this.
And there you see: Larry Moe and Curly
being displayed by this function right here.
Now in this case, we really don't want this display
function to modify stuff, right.
I mean it's only displaying vector elements, we don't
want it modifying anything.
So we could get this to modify something.
That's not what we want to do, but we certainly could.
To remember that we could do the at method of the vector class,
well, we could simply do star v, right, de-reference this pointer,
that gives me the vector, then I could say .at 0 equals funny.
And what that will do Is it'll change the first vector
element, Larry to Funny.
Notice the syntax.
The syntax may be a little strange.
But think about this, this is very logical, right.
If i de-reference the pointer, I get the vector.
And then once I have the vector, I can do .at, .size
whatever else I need on it.
So this sets that to funny.
I could also come over here and do something like v,
which is the pointer, right.
There's null pointer.
So now I'm not pointing anywhere.
So if I do both of these, you can see that this will
compile just fine and run.
Now if I move this to the top right there, now I'm actually going
to change that vector element.
So when I run it, you'll see funny now instead of Larry,
you see that right there.
So this is not something you want to happen, right.
It's a display function.
It shouldn't be messing around with the vector that you're pointing to.
So in this case, we could use the const qualifier here,
right, that will prevent this from happening right there.
So if I do this now, I'll get a compiler error right there.
You can see the red arrow saying, hey you're telling me that,
that vector I'm pointing to is constant, you can't mess with it,
you just tried to mess with it.
So that won't be allowed.
And if I put a const here, then this line 13 won't be allowed.
I'll try to compile that, and there's the error.
Because now you're telling me that the pointer is constant, but
you just tried to change it here.
Okay, so again that's not what you want to do here.
All right, so now it's a lot safer this function.
We can't change the vector, and we can't change the pointer either.
So let's look at one last quick example, and I'll clear this out.
And what we've got now is let me close this up.
We've got another function called display because we're
using function overloading here.
Remember, we can use the same name for the for two different functions.
And let me comment this piece out, and I'll uncomment this piece right here.
Okay, so in this case, I have an array of scores, right,
which is an array of integers.
And I've set them all to these scores, and I've got a negative 1 at the end.
In this case, the negative 1 is a sentinel.
This is where I want to stop processing.
So what I'm doing in this display function here is I'm passing in the
address of that first integer and the sentinel, where do I want to stop.
And you can see what this is doing, it's saying while what I'm pointing
to right there is not equal to the sentinel, which, in this case, is -1.
Then process what I'm doing, right.
So I'm going to basically de-reference that array, display a
100 and then increment the array, the pointer to the next element.
So think about what's going on here.
Here's the array.
And let's just put a few numbers in here: 100 98 97 79 85 and -1.
I might have missed one, but that's okay.
So at this point, that's my scores array.
This is scores.
This is, let's say, address 1000, right.
Perfect.
So now I'm passing in scores.
So now my array variable in the function points right there.
And my sentinel is -1.
All right, so am I pointing to negative 1?
No, I'm not.
I'm pointing to a 100.
All right, print out 100, and increment the pointer.
Where's the pointer pointing to?
Well, now the pointer is going to point here, not here.
So now we're going to loop again and print out a 98.
And we're going to keep doing that until we hit -1.
So this is going to print 98 97 79 85 and then it's going to stop.
In this case, we could pass in constant for the array, right.
We're pointing to these numbers, we don't want to change it.
But we are actually updating the pointer here.
So we can't have a constant pointer, right.
We can have constant a pointer constant integers, but not a
constant pointers because we're actually changing the pointer.
This is something, in this example here, that you
can't do with references.
You've really got to use pointers to do this kind of stuff.
Okay, so that wraps up this video.
There you see a couple of different examples of pass
by value with pointers.
At this point, you might be thinking do I use pointers, do I
use references, how do I do this?
Stay tuned. In the last video in this section, I'll tell you exactly
when you should use pointers and when you should use references.