In this video, we'll learn about constructor initialization lists,
which are very useful for efficiently initializing our object's data members.
So far we've written our codes so that we initialize our data member values
in the constructor body by assigning values to them.
While this works, it technically isn't initialization
because by the time the constructor body is executed,
these member attributes have already been created.
So we're really just assigning values to already created attributes.
I'll show you exactly what's happening when we head over to the IDE in just a bit.
What we really want to do is
have the member data values initialized to our values before the constructor body executes.
This is much more efficient since it's true initialization.
C++ allows us to do this using constructor initialization lists,
which is basically just a list of initializers immediately following the constructor
parameter list. It sounds complicated, but it's not, let me show you.
Here we have the same player class that we've been using in previous examples.
It has three overloaded constructors. And if you recall from the previous videos,
we implemented them using assignment statements in the constructor body.
You can see in the top section of this slide,
how we previously implemented the no args constructor.
In the body of the constructor, we use three assignment
statements to set the attributes to the values we want.
While this works, it can be inefficient in many cases.
For example, by the time that we get to the statement name equals none,
the name string object has already been constructed and initialized to an empty string.
So we're really just assigning a new string to it, in this case, to an existing object.
That's very different from initialization.
What we really want is to initialize the data members to our data values
as they're created.
That's what constructor initialization lists allow us to do.
The bottom section of the slide
shows how we could implement the same constructor in a more efficient way.
Notice that immediately after the parameter list, we provide a colon
followed by a list of initializers.
In this case, we're telling the c plus compiler to initialize name to none
health and xp to 0.
This happens before the body of the constructor is ever executed.
One thing to keep in mind, the order in which the members are initialized
is not necessarily the order we provide in the initialization list.
The data members will be initialized in the order that they were declared in the class declaration.
So let's implement the rest of the constructors using initialization lists.
Here we're implementing the single string constructor.
Notice the previous way on the top section of the slide
and the better way using an initialization list below.
In this case, we provide name value
to initialize name and still use 0 for health and 0 for xp.
You could probably guess how the three args constructor will look.
Here's the three args constructor at the bottom using the initializer list.
We're providing name val, health val and xp val to the initializers
and the complete refactoring looks something like this.
Notice how in the constructor, there's no code in the constructor body.
We can still write any code we want in the constructor body.
But now we can be sure that our data members have been initialized to our own values
before any code in the constructor body is executed.
Let's head over to the IDE, and we'll step through a few examples so you can see
how much more efficient constructor initialization lists can be.
Okay. So I'm in the ide,
and I'm in the section 13 workspace in the ConstructorInitializationList project.
And I've just got a simple main here that has our player class as
I've discussed previously with three overloaded constructors:
no args, a single string and the one that supplies
the string and the two integers.
Okay. And I've implemented the constructors that we've done
previously using these assignment statements inside the body of the constructor.
I've got some break points in here that we'll walk through so that we can see exactly what's going on,
and then I'm creating three objects: I'm creating empty using no arguments,
I'm creating frank which is a play -- they're all player objects.
Frank with the single string, and then villain
is going to use this constructor here with the three arguments.
Okay. So let's walk through this, and we'll be real
careful to look at that name
attribute because that's really the important one because it's an object.
So let's walk through this.
And right now we are on line 41 right about here,
and I'm going to step through this,
and that will call the no args constructor, that's this one right up here
on line 21 since we're providing no information for initialization.
So I'm going to step through it.
And you can see now the arrow here the little green arrow is on line 22, that's where I'm at.
Now we can't really see empty here because empty is out of scope.
We're now within the scope of this constructor right here.
And I'll talk about a variable called this a little bit later in the course,
probably a few videos from now.
This represents the current object. Okay.
So if I expand this,
you can see that this is this current object that I'm building right here.
And you'll notice something interesting, you'll notice that name is set to the empty string.
What does that tell you? Well, that tells you that that was already initialized. In other words,
that string object name its constructor was already called
with no information, and we initialized it to an empty string.
So this line right here that says name equals none,
that's really not initializing anything. All it's doing is assigning
none to an already created object name right here.
That's really not what we'd like,
we'd like to initialize that object name
immediately without having to initialize and then assign to it.
Okay. That can be very inefficient.
In the case of a very complex class, you might have to create some sort of a
default constructor for it and it's setting a lot of fields, it may be allocating things
and then you're just going to deallocate all that stuff and assign to it again.
It really doesn't make sense things become very inefficient.
So you can see in this case, I'll keep walking through this.
And now we're going to set name to none, health to 0. You can see I'm right here on line 24
and xp to 0. Then I come back down to main.
At this point, my player object -- I'll refresh over here,
my empty player object is set to none 0 0, just like we expected but.
Now let's create the frank objects. So what do we do?
We're going to call the constructor that expects a single string, which is this one right here on line 27.
And I'm going to go to that. Now I'm here online on line 28.
Again notice, this represents the object that I'm creating right now
and an empty string again. So I just created another object.
In this case, I'll step through it really quickly
and now I'm back here to player villain, which is going to call this constructor right here,
the three args constructor.
And I'll do that. And again, here's this another object that was created.
So we've just created three string objects
and then get rid of basically the string, the empty string they pointed to and replaced it with
frank villan and none. So really really an inefficient thing to do.
And what I'll do is I'll make one little change that hopefully will really
help you understand this. Right now, we're just using that empty string.
But suppose that I initialize this here to some
string that's really obvious, like a bunch of x's.
Okay. And let's let's run this again and we'll walk through it one more time.
And hopefully, this time it'll really be obvious what's going on.
Okay. So again, I'm here on line 41,
and I'm creating an empty player object so it's going to call the no args constructor, this one here.
So when I step through it, you can see I'm now in line 22.
But if you look at the object, take a look at name right there, see all the x's,
so that tells you that some constructor for that string class is already executed
and initialized that string object. Again, that's not what we want to do.
Okay. So hopefully, this this is really clear as to what's going on.
What we want to do is, we want to use the initializer lists for the constructors.
And it's really simple to do.
What you do is immediately after the parameter list,
right, there you just put a colon
and you can follow it by the initializer list, just like we did in the slides.
Okay. So in this case, I'll do it on the next slide just so it's a little clearer there.
What we can do is we can tell it which attribute do we want to initialize.
Well, in this case, I want to initialize name and we provide the initializer,which is the
initialization value, I should say, which is none,
health
to 0. All of these would be comma separated,
and xp also to 0.
That's it, and then we don't need the body of the constructor
anymore because we've already done the initialization.
We could certainly write any code we need here,
but we're sure that when we're in the body of the constructor,
those three attributes have now been initialized, initialized correctly,
not initialized and then assigned to, but initialized.
Okay. So that takes care of that one.
We can also do the same for these here, and I'll just do them really quickly.
And let me just copy this bit here.
And what we'll do here is we'll set name. In this case, we have the value to set it to,
it's going to be named val,
and we'll still keep health and xp at 0, and we'll get rid of the constructor body.
We'll get rid of some of those break points as well and clean up the code.
And you can see when you do it this way you end up with empty
bodies for the constructors.
And that's okay because obviously we want to put something else in there once our variables are created.
And this last one, again, I'll copy this one just to save a little time here.
We'll get rid of that, and
I'll indent that in. There's my initializer name val. In this case, I've got health valve,
and I've got xp val.
And that's pretty much it. I'll get rid of this.
And there you go. That's the final refactoring.
You can see now we're using the initializer lists
to initialize our objects, which is exactly what we want to do.
Let me get rid of that extra colon right there.
And that should do it. Other thing is
i put the order in here as name, health and xp.
That order doesn't really matter. It's going to be initialized in this order
name health xp whatever order you declare these guys in right here
in your class, that's the order that the initialization will take place.
It just happens to be the same order that I've written here,
and that's pretty much best practice is to keep the order the same.
But don't rely on order here.
The order is going to be the order that you declared these things in.
Okay. So there you go. That's initialization list now you'll do you will notice a few things.
We're going to talk about delegating constructors soon so we can get rid of some of this
extra code because if you think about this, this is really the same as this it's the same as that
and it's the same as that.
So we'll have a little bit even more efficient way of doing this.