Welcome to the section 17 challenge.
I'm in the section 17 workspace.
And you'll notice that I've got two challenge projects here.
The first one is challenge-1
and that's the hardest that I'm going to give you,
that's the basically you have to write three functions for this challenge.
And I'm giving you the function prototypes, and you have to write the functions.
There's also the challenge solution-1. That's my solution to this challenge,
and we'll do that in the next video. Also notice that there is a challenge-1.
So that implies there's going to be a challenge-2.
I'm planning to put another challenge in this section
in which we'll implement a doubly linked list using
raw pointers, and we'll replace the raw pointers with smart pointers,
so you can really play around with it.
The best way to understand pointers or even smart pointers
is just to play with them to create examples to try them out,
make mistakes, understand why this doesn't work.
You'll try to copy a unique pointer,
and it won't work, and you'll go oh yeah of course you can't copy unique pointers.
So this is the idea is just to play with this and
get more experience using it. So that's what this challenge is all about.
In this challenge, we're going to create
a real simple main that's going to instantiate a vec pointer.
And I'll show you this vec pointer right here.
And then I'll talk about the challenge in more detail in a sec,
but let's just get an overview of what's going on here. You can see here's my main.
And these are the three function prototypes and you'll have to implement
those three functions, but let's talk about the main first.
Main has vec pointer. Okay. So here's vec pointer.
And what does vec pointer look like. Well, vec pointer is on the stack,
and it is -- and this may look a little complicated this declaration here,
but break it down into pieces, and it'll make a lot of sense.
Vec pointer is a unique pointer. Okay. So it's an object.
And this is on the stack here.
So what is a unique pointer. We know what a unique pointer is, right. A unique pointer is
basically an object that manages a raw pointer.
And in this case, it's a unique pointer. So I'm pointing somewhere.
Where am I pointing. Well, I'm pointing to a vector.
All right. So here's my vector. Remember, a vector can have multiple elements.
So here's my vector.
Now notice everything over on this side is on the heap, right. All of this stuff is going to be on the heap.
The only thing that's on the stack is that vec pointer right here.
So now we've got a vector. Okay. I know what that is.
Well, what does the vector contain. Well, the vector elements are shared pointers.
So each one of these guys
is going to be a shared pointer,
right. So I'll just put sp here so you know what I'm talking about.
So what's a shared pointer. Well, a shared pointer is an object.
And the shared pointer in this case manages a test object.
And we've got a test class right up here, same one we've been using in this section.
So this guy now has a test object that it's managing.
And this guy is managing a test object and so forth.
So this looks pretty complicated.
And it's not that complicated when you really break it down like that.
Again, all we've got on the stack is a vec pointer.
That points to a vector on the heap,
that vector contains shared pointers,
and those shared pointers refer to test objects.
Okay. So how are we going to do this. Well,
I'm going to do this really easily because the vector and the test class,
the unique pointer class and the shared pointer classes really do most of the work for us.
And we're going to do this with no news and no deletes.
Okay. We're not going to use new. We're not going to use delete.
We're going to use make shared, make unique,
and let the destructors be called automatically when the reference counts
go down to zero or when the unique pointer goes out of scope.
So this is going to make our memory management really, really simple.
We're not going to work with raw pointers at all.
All right. So that's the big picture.
So now what are we doing. Let's walk through this main. And I'm going to clear this out real quick.
And let's walk through our main one step at a time here.
So here we've got a vec pointer. That's just going to create that object on the stack.
It is not creating that vector on the heap, we need to do that ourselves.
So again that vec pointer is just that simple unique
pointer object on the stack.
In order to create that vector that we're pointing to,
we need to call this function make and that's this function right up here.
There's the function prototype right here. You can see make, right, over here.
Again, this looks really complicated, but it's pretty straightforward again.
What are we returning from make. Well, we're returning
a unique pointer to a vector of shared pointers that manage test objects,
right.
So inside make is where we're going to use make unique.
They're going to actually create that unique pointer and make it point to that vector.
Okay. Once we've got that, we're going to ask the user how many data points do you want to enter.
And let's say they type in three.
We'll read that into num, and then we'll call fill.
And look what we're passing in to fill, we're de-referencing vec pointer.
Well, what is vec pointer? Vec pointer is a unique pointer to that vector.
So when I de-reference vec pointer, I get the vector that it's pointing to.
So I'm calling fill with the vector and the number of elements.
And you'll notice that here's fill right here.
And all fill is going to do is it's going to loop as many times as the user wanted,
in this case 3, and it's going to say so what's the first integer you want to enter, you'll type in 10.
What's the second one, 20. What's the third one, 30.
And for each one of those integers that the user enters,
we're going to create a shared pointer
to one of those test objects with that integer they entered right here,
and we're going to put that on the vector using pushback.
That's it. Now we'll call display. Notice, again,
we're de-referencing vec pointer that gives me the vector
and display is right here on line 69.
And all we're doing in display is we're just
iterating through that vector of shared pointers
and displaying whatever data those test objects hold.
It sounds complicated, it's not so complicated.
You just need to break it down into little pieces and take them one step at a time.
Let me run this for you so that you can see what the output looks like.
And I'll run it based on my solution here. And let's build and run.
So the first thing it says is I'm going to just slide this over here so you can see the actual
code next to it. So here's my main right here.
How many data points do you want to enter? Let's say I want to enter five data points,
enter data point 1.
Now we are -- right now we're in that fill method.
The fill method is one that's going to loop five times in this case,
each time asking me for what data i want.
It's going to make shared, right, and create that shared pointer to that
test object that has whatever I type in. So let's say I want to type 10.
Now you'll notice that over here on the right, we've got test constructor that's just a little
debug statement that I put in there to help you out.
It's being indented so that you can see it.
So what's happening here is we've just created a test object with a 10,
which is what the user typed in. So let's create another one 20.
Remember, we're going to get 5 of these. So we'll do 30, 40
and 50.
So at this point our fill is done. Now we're going to display
all those elements in that vector.
So when I press enter now, that will be called display, and it'll display everything.
There we go. It says display vector data 10 20 30 40 50.
Now look what happens.
Test destructor 10 20 30 40 50. Again, I've got a little simple print statement
in the destructor for the test class.
And you can see that these objects are being cleaned up off the heap, which is really cool.
So no deletes necessary because we're using smart pointers.
And this is the output that you should get from this main
once you implement those functions.
So there you go. It's up to you now.
What you need to do again is implement, make, fill, and display.
And if you scroll up just a little bit here and it's also in the description text,
it tells you a little bit more about what those functions should do.
So again, the function make it creates and returns a unique
pointer to a vector of shared pointers to test objects.
The fill function expects a vector of shared pointers
to test objects and the integer for however many numbers the user wants to enter.
And it prompts the user and creates those shared pointers as it goes.
And then the display just displays everything in there.
And if you look at the function prototypes that I provided,
and you can change these to whatever you like. If you want to try it with
without the ref, with the ref,
const, non-const, try it out, change them around and see what happens.
But these are the function prototypes I'm giving. You can see that
make, expects nothing and returns a unique pointer.
In this case, fill expects a ref to a vector.
Now this one has to be a ref, right. It can't be by value.
Otherwise, you won't add anything to the vector.
And it can't be const because we actually need to change that vector.
But display should -- we should expect a ref, and it should be const.
So in this case, I want to be efficient and not copy that vector.
And at the same time, I don't want to change it accidentally. So there's my const.
All right. That's it. Good luck, have fun, play around,
change these prototypes if you like,
use the debugger, I'm sure that'll help you a little bit when you're trying to learn this stuff.
So those are the three. You shouldn't have to change the main,
and you should get the same output as I did.
We'll come back to the next video, and we'll do the challenge solution.
And you'll see that it's actually pretty straightforward.
It's real nice to be able to have c++,
manage all this stuff for us using smart pointers.