All right.
Welcome back to another lesson for this object or any programming section of the course.
So we're rolling forward with the kind of same code that we had before with the car class.
Except in this light, some make some small modifications to the code and we're going to go over a couple
of new concepts.
One of those concepts is something that I mentioned in the last lecture, which is for us to use one
type of smart pointer that can do reallocate itself.
So we do not have to do something like this where we are explicitly deleting cars since we've dynamically
allocated it.
So we are going to do that, and then we're also going to go over an interesting concept where we try
to create a new object and say that it's equal to some existing object so we can make a copy.
And we're going to talk about what that does and where it can kind of have some potential issues.
So let's go ahead and get started.
So first off, I and talk about how we can use this thing called a smart coin.
And there's multiple types of smart pointers, but we're going to just use one today called unique pointer
and what we're going to do as kind of make another car object just like this and we'll dynamically allocate
it.
But when we use this smart pointer, it's going to allocate itself.
We won't have to put the delete key word for it.
So let's go ahead and get this started, so we're going to actually have to include something for this.
We need to include a library and this library is called memory.
Seniors, some, including memory here.
So what we're going to do is we do Stevie, Colin, Colin and then we do unique pointer.
And you notice that this comes up right here, so I can just press tab and you notice that what comes
after the key word unique underscore pointer is the type of pointer that is, you know, the type of
pointer, what it's really pointing to, which will be type car, right?
We want to make a car pointer, so I press tab.
It spells out this unique pointer for me and then inside of these angle brackets here, similar to what
we use for vectors, you know how vectors we can say, enter something like that.
And here we can also say card for a vector two.
But we're going to say car and here to say that we would like a pointer for type car.
So then after this, we can put the name that we want.
So I'm going to call this car three and then we're going to put some parentheses and inside the parentheses,
I'm going to say new Capital C car, and I could put some of these in here.
I can put some like parameters, but I'm not going to use this parameterized constructor and actually
going to use the default constructor.
And what I'd like to show you is I've modified the code a little bit in here.
So I have actually added I have something in the bottom there that I'll talk about in a second, but
I have added a default constructor as well, so I'm making it so we don't have to use a parameter as
constructor.
We can use a default constructor as well, where everything is just zeroed out and empty strings for
the brand model and paint color, zero for odometer, zero for fuel.
This is something I talk about in a second that I have added, we'll talk about that when it comes to
making copies of objects.
But, you know, I've just like to say that I've made that, you know, we have this default constructor
here prototype before, but we never really implemented it.
It was just there and it would have just kind of allocated memory, but we have not really initialized
any of these members.
Now we are initializing these members in an implementation of the default constructor.
So this wasn't here before, right?
We didn't have this here before.
We just had a prototype for it.
There was this thing right here.
Now we're making it so we can create default objects and we have default initialization values for all
of these.
And once again, ignore this.
For now, just focus on these other ones.
So this is how we make a unique point.
We're not saying what the paint, the brand, the model and the models are.
We're just saying make me a new car and that new car is going to be dynamically allocated.
It's going to be a pointer car.
Three will be a pointer to a dynamically allocated car object and it is going to hold all the values
that are here in this constructor.
This default constructor, this is the default constructor empty parentheses here.
This parameter is constructor.
All right.
So now we have this pointer, it's going to automatically get the allocated notice.
We have three things now we have car car two and car three.
So let's go ahead and run this code here and see what happens as far as what's called for the destructor.
All right, so you notice that we actually get the destructor called three times.
So you notice before I just had this daily car, so this object right here, when we comments it out,
you'll notice that one of these goes away.
Now there's only two, so this one needs to delete, right car needs to be explicitly deleted because
it's just a normal coin.
It's not a smart pointer yet.
This one here is a smart pointer.
And more specifically called a unique pointer.
And once it goes out of scope, it gets rid of itself just like the stack allocated one here card two.
So once Card three, even those dynamically allocated once it goes out of scope, since it's a smart
pointer, it'll automatically delicate itself and then you can just use it similar to everything else.
Like you can say, Card three get odometer instead.
Like, you could just put these right here and I run this, and it's going to give me some different
results, obviously, because, you know, these are just the zero and this is an empty string right
for paint.
Paint was just a totally painkiller with an empty string.
So that's why you see this empty string is use zero for the odometer, right?
Because that's what it got initialized to with the default constructor.
We haven't set anything for it.
I just made this new car without any parameters because I didn't use the parameter constructor.
I use the default constructor, which is right here.
And so that's why we see a zero printing out here and an empty string printing out here.
So I just want to show you that you can use the arrow the same way it works the same way, it's just
a smart pointer, so it doesn't need any explicit cleanup by using the delete key word.
OK, so now we're going to talk about something else, so I'm going to go ahead and make a nother object,
and I'm just going to call this car for.
And I want to show you what happens if I say car car four equals car to.
So now what I do is I'm making a new car and I'm sitting in an equal to an existing car.
This already exists.
So.
What I would like to show you is kind of what happens here, so I might go ahead and let's see, we
have to.
Let's go ahead and print out.
Let's see, I say.
Let's just do a s t c out, and I will say car for dot model jet model, OK, so.
Typing is still slow, so we're going to see our car for you while in fact, I'll say.
Team car for a model.
So I'll say that just so we can see it better in the output.
So right here, I'm just saying car, car, car making a new car, right, so this is us declaring a
new car.
It's not dynamically allocated.
It's just normal, normally allocated.
So I'm saying new car car for not not new.
I don't mean new like this.
I'm just making another object.
So car car four equals car two.
And then I say printing car for model.
And let's see what.
Let's see what it prints out.
And you notice there's also another destructor call here automatically since we're just making those
two allocated car.
So it says printing car for model, I input a space there, but it says Fiesta.
So it's the same as Car two, right?
We said car four equals car two.
You know, I can go here and I could say car for, let's just say, give brand something like that.
And you know, this is going to be smashed together, but whatever.
So I'll run this and let's see what it says.
So it says printing car for model and it says Fiesta Ford.
Right.
So it's totally the same object.
Is this if we kept printing like paint and miles, it would be the same miles.
So it's set to the same attributes, the same number of variables as car two.
So essentially, we've made a copy.
Right?
Well.
Kind of kind of, yeah, this is this kind of makes a copy when I say kind of I mean, what it's really
doing is just copying over the members in what we call a shallow copy.
And I'm about to show you an example now of a problem that can occur.
With shallow copies, and then we're going to talk about how to fix it with something called a deep
copy and using a special constructor.
So right now, what's happening is it's just basically copying over all of the members that car who
had all of the data members.
So let's head over to the class here, so what I did was I actually made a new data member here, so
I called this upgrade code, so it's just a vector of integers, but it's actually a pointer to a vector
of integers.
And that vector of integers, the upgrade codes are just like.
Packages that might come, you know, maybe have the sport package and that's like code one and then
you have like the Lake Luxury package in that code two or something like that.
So let's head to a copy.
So what happens in the default constructor with this?
Well, what I say is I say upgrade codes and this is a pointer, right?
So it's a it's a pointer to a vector, and I say upgrade code equals new.
So I'm dynamically allocating a vector for this.
And then what I do since this is a pointer, I use the arrow and I push back one.
So by default, let's say you get the base package or something like that base package upgrade.
Maybe it's not even OK.
I mean, it's like you get like a media upgrade, right?
So default car comes with a media upgrade, which is like code one or something.
So I also have it here.
When you choose your paint and brand and all that with this parameter as constructor, it also pushes
back this like code one, which we'll call the media upgrade or something like that to the car as well.
So I also have this function, no function down here called add upgrade, and it's actually lets you
add a code to your upgrade codes for the car so you can add an upgrade.
Let's say you want to add a sport package or something, and maybe that's code two.
So let's head back to main.
So what I want to do is I have this car for equals car two.
And so I'm going to say, you know what?
I want my car four to have an upgrade, for sure.
So I'm going to say car for Oops, car for Dot and I'm going to say, add upgrade.
And I'm going to say, let's add code two, which is like some type of sports package or a luxury package
or whatever.
So I go ahead and I add this now.
I want to show you in the debugger what is what's going to happen here, so I'm going to put a full
breakpoint right here and when we go ahead and debug and we get we're going to examine this stuff here.
So I'm going to try.
OK, I can't really zoom in much more here and figure out how to do that.
Yeah, after subsequent lectures, figure out how to make this bigger, but hopefully you can see,
OK.
So let's take a look at Car two, because that exists at this point, right?
We have car and car to this line hasn't been processed yet.
We stopped on it, but it hasn't been executed yet, so we haven't created Car three yet.
So let's look at car to what is car to have for its upgrade codes.
Well, it just has one in here, OK?
Because that's what comes with the basic like when you just get a car just comes with one, right?
And that's coming from up here.
Right.
So here here and the default constructor in here in this parameter as constructor.
So just want to remind you that.
So let me go ahead and step over, so I step down to here.
Now we have car three.
And then what I'm going to do is I'm going to step to the next line.
Remember, it's not going to execute this next line yet.
It will execute this line, though it won't make car for.
So I say car for now.
Let's go ahead and take a look at Cartoon Car four again.
So car for.
Upgrade codes.
It just has one as expected, right?
Yes, we made a new car, but we said it was the same as car to.
So Car two also has one, so that looks right, right?
It's the same thing.
It's made a copy of car to car for should be the same thing as car two, so it looks good, right?
They both say one for upgrade kits.
I'm going to go ahead and step to the next line and what is going to do is it's going to execute this
line nine when it's going to add upgrade to to car for.
So let's go ahead and check this out, so I got a car for now.
I look in the upgrade codes and it has one and two it added to.
So that that that makes sense, right?
We wanted to add an upgrade to it now it shows up in the vector.
Sounds good to me.
And what's the problem?
Let's go ahead and take a look at Car two, though it should just have one, right?
Oh, but it doesn't have one car.
Two also has the code to added to its vector now.
And why is that?
Because what it did was it just literally copied over the same member, right?
I said that what it does is it makes a shallow copy which is just copying over all the data members.
Let's take a look at those data members again.
This all seems good, right?
Fuel tank and just copies, etc. That's what we want, right?
But what it does is it copies this over to right.
And what is this?
It's a pointer.
To a victor now here you see the problem, what it did was it copied over the pointers, so Car two
and Car four are both pointing to the same memory address for the vector.
So when I modify one, it modified the modifies the other because it's just the same memory is pointing
to the same vector that was dynamically allocated on the heap.
So whenever I change car for is going to change car two and whenever I change cards to and I don't mean
in general, I mean when I change the vector, if I add stuff to Katya's vector, it's going to add
the same thing to car force vector.
So I add stuff to car.
Ford's vector is going to have the same things the car to vector, and maybe we don't want that.
We just said car for an upgrade.
I don't want to add it to car, too.
So therein lies the issue.
This is a shallow copy, and we're noticing a potential problem that can happen with that.
So how do we fix this?
Well, here comes another concept yet again.
So we're going to make a special type of constructor mint for making copies, and that's called the
copy constructor.
And so let's head back over to our code.
So what we're going to do?
Is we're actually going to put it up here, and I'm going to put it right after this one here, and
I'm going to say car some and make this constructor but what it's going to have.
This is going to say it's going to say a car.
So what we're going to have is going to have another car passed in the parameters here.
And so I'm just going to call this object like that car and object, and it's passed by reference.
So this is how we make the copy constructor.
It looks just like the normal constructor says car and kind of, you know, same as this one.
But in the parameters here, we're doing something special and this is something that is going to be
recognized.
C++ is going to recognize this.
So we're passing a car.
Object by reference.
Into here and what this is going to be is it's going to be the car on the other side of the equals sign.
So in here we say car.
We're making a new car, right?
So whenever we make a new car, we should call a constructor right.
But what constructeur are we going to call?
Well, we're going to call a copy constructor.
Why is that?
Because this is making a new car in the highlighted section here.
Then we have in one equals sign, which is for assignment.
And then we have an existing car, which is car two.
So this highlighted car car two right here is actually going to be represented by this car and obs here.
So this parameter is going to be what's on the right side of the equals sign, which is car.
And our responsibility now is to implement this.
And I want to explain the other constructors here, so I'm going to put it up here and one copy paste
it.
And our responsibility now is to make sure to copy over everything that's in, you know, copy over
all the other members and copy over everything that's in the vector, but don't have it be the same
point or we want a brand new vector for our car.
So what we're going to do is we're going to put all the we're going to like put all the member functions
here, I'm sorry, member variables here.
So I'm going to say fuel and what I'm going to do is just copy everything over like normal.
But when it comes to the vector, I'm going to make a new vector so this car forward will have its own
vector.
It's not going to try and use the same exact memory like as car, which is going to be OBJ right here
is going to be car to pass by reference.
So I will say fuel equals obj
dot to your.
So and then what I'm going to do is I'm going to say all of this for all the other one, I say odometer
equals.
Object shots.
So Australia Day odometer and I'm going to have to do this for each one, I'll say painkiller equals
object dot painkiller.
And then now when I get to upgrade codes will actually let me do brand first, some I say brand equals
object brand.
And then here we have the what is this model?
So model equals object model, and now I come to the upgrade code, so I'm going to say upgrade codes.
But what I'm going to say?
Is upgrade codes.
Equals new and I'm actually just going to copy all this, I want to make a new vector.
Once what's at stick on me, see what's going on.
Caitlin, face that here, and then what we want to do is we want to add all the stuff from objects
factor into here.
So I'm going to say or and I.
Equals zero.
I will say so actually, what I will do is I will say.
No, this will be fine.
I'll say NTI equals zero.
I is less than and I will say object.
So, object, what, uh, upgrade codes.
And this is going to be an arrow because it's a pointer, right?
And we arrows size and then I will say it plus plus.
So we're going to go the first.
Many times we're going to look for as many times as there are objects and as there are codes in this
other object, which will be this remember Car 2's upgrade codes vector
when I need to do something like this.
So I'm actually going to say auto v, I make some kind of vector.
Actually, I just say temp equals, and what I need to do is, do you reference this object?
Dot upgrade codes, because it's a pointer to a vector, and then I'm using the auto keyword to automatically
detect like that.
It's a vector so you can use auto and it will automatically detect the type here.
So right now, it's knowing that this is a vector of integers because I'm d referencing the pointer
object of great curves is a pointer right at pointer to a vector of integers.
So what I'm doing here is I'm d referencing that.
So now we have a normal vector and then what I'm going to do now is I'm actually going to say upgrade
codes, aero push back.
And then in here, I'm going to say temp I.
So what I'm doing is I'm just copying over the all the values that are in the.
This objects of great codes over to the current objects of great codes, when I say current, I mean
like car for right, we say car, which is like, make a new car.
What do we call it car for?
So what it does is it says, OK, I see this, I see this.
I see you want to set it equal to you.
I see what you want to do is you want to want to make a copy of Car two and have that be car for.
So what it does is it goes here and it calls this copy constructor and it says, OK, this is car to
now pass by reference.
And this stuff over here, that is just the data members of the class is the.
The object that is being called upon another way you can refer to this is some using the keyword this
so this dot upgrade code is something like.
Yes.
Can you change into a point, for this instance?
Looks.
This arrow of great codes or this upgrade codes is a is referring to car for in this example.
So it's the object that is being called upon.
So same thing here, like a car.
Arrow jet fuel car is the object that's being called upon.
All right, so that's that that would be referred to as this, but we don't need to put that like we
can just get rid of this.
I mean, this is upgrade codes.
This is the upgrade codes of car for it's the one that is being called upon.
This is the object that's being passed to the copy constructor for us to put copies of into these guys
over here.
I.
All right, it's all we're doing is coughing all the stuff over from cartoons, vector into car force
vector, which is the object, this being vehicle.
OK, so once we do that, it should be all good.
And so let's go ahead and see how this plays out now.
So we have this same thing where we add the upgrade to, but things should change now, so let's go
ahead and put a breakpoint.
Let's go ahead and run it, and let's see what happens, so we will step over here.
Car foreign, you should both have one.
So we have let's check the upgrade code, so we have one in there, so that's totally fine.
And then let's go ahead and check out car for.
So this just has one as well, which is good for now, so let's run this line right?
And then now let's see what happens.
So Car four has two, which is what we want, but let's check car to.
COTU only has one now, so it didn't modify a cartoon because what we did was we made it have its own
vector, so each object is going to have its own vector even if it's making a copy.
So this is a new vector.
So Carrefour had its own new dynamically allocated vector.
And we just copied all the stuff over when we made the copy.
So at this point in time, Car two only had one and then as far as that, Vector had code one only.
So that's why car for only had code one.
And then now we add that of Card Carrefour, which has two.
And it did not modify Car two.
It only modified Carrefour, which is what we want.
OK, so kind of a lot of stuff, but I'm yeah, I'm not going to go over anything else in this lecture.
I just wanted to touch on those few things.
So the unique pointer, remember that this is a smart pointer that will allocate itself.
We don't need to delete it.
And the this right here, if you don't have a copy constructor, it is going to make a shallow copy
where it just copies all the members over straight up.
So it would have copied that pointer over and it would have been pointing to the same piece of memory
cartoon Carrefour would have been pointing to the same piece of memory for the vector, is what I mean.
So the vector here would have been the same piece of memory for car two and car for Intel.
We made this right here, the copy constructor, right?
Here it is in the header.
Made this copy constructor.
Here it is in the implementation file.
The banking sector where we copy everything over, but we make sure to make a new vector for this right?
New dynamically allocated vector and then we go ahead and we copy everything that was in the McDeere
over.
So now when you're here and you're seeing this and you have a copy instructor, you know that it's going
to make something called a deep copy.
So you're the one controlling what happens when you make a copy and have a new object that gets set
to a copy of this existing object?
OK, so we're going to kind of continue on to the next lecture with something about assigning things
that we want instead of making a new copy.
We'll try and see what we need to do if we want to have a shallow or deep copy for setting one car equal
to car to.
So if I made like a car car four by itself, like with a default constructor or parameterized, and
then later on, I want to say Car four equals car two and I wanted to have it be the same as Car two.
We run into the same issue with the shallow anticorpi, and so we're going to have to implement yet
another special function in here, like the copy constructor that will handle that.
OK, so with that, I will see you in the next election.