WEBVTT

00:00:00.640 --> 00:00:05.400
Standard array class is a thin wrapper over a regular static array.

00:00:05.410 --> 00:00:06.400
However,

00:00:06.410 --> 00:00:09.270
the replacement for dynamic arrays from the standard

00:00:09.270 --> 00:00:12.660
library is a lot more powerful and flexible.

00:00:13.040 --> 00:00:16.720
I am, of course, talking about the famous Vector class.

00:00:16.720 --> 00:00:19.060
So let's first include the vector library.

00:00:19.740 --> 00:00:22.790
The next few lessons will be dedicated to working with vectors,

00:00:22.790 --> 00:00:27.450
and I want to do these demonstrations by using our own Subject class.

00:00:27.840 --> 00:00:30.180
The last modification to this program was the

00:00:30.180 --> 00:00:32.350
introduction of the standard array.

00:00:32.360 --> 00:00:34.460
So let's pick up where we left off.

00:00:34.840 --> 00:00:38.240
I will add a special message to all of the subject constructors,

00:00:38.240 --> 00:00:43.150
because I want to show you what vector does with the objects in the background.

00:00:43.540 --> 00:00:47.910
I only need to add a message for the default and parameterized constructor.

00:00:47.920 --> 00:00:52.060
Other constructors already have a message from the previous demonstrations.

00:00:52.840 --> 00:00:55.650
Now, let's go down to the main function.

00:00:55.650 --> 00:01:00.950
Here, I created the dynamically allocated array of subjects on the heap.

00:01:00.960 --> 00:01:04.560
The size of the array is taken from the variable at runtime.

00:01:05.640 --> 00:01:07.470
However, in modern C++,

00:01:07.470 --> 00:01:11.060
there is a better solution for allocating arrays on the heap.

00:01:11.070 --> 00:01:13.650
We can use the std::vector class.

00:01:14.440 --> 00:01:15.870
This class is templated,

00:01:15.870 --> 00:01:20.650
so we need to pass the data type of the array elements as a template argument,

00:01:20.650 --> 00:01:24.660
and we will also pass the size of the array to the constructor.

00:01:25.540 --> 00:01:27.220
Let's compile this now.

00:01:27.220 --> 00:01:31.810
As you can see, the default subject constructor was invoked three times,

00:01:31.820 --> 00:01:35.160
which makes sense, because the size of the array is three.

00:01:35.840 --> 00:01:40.460
So now we have a dynamic array on the heap with three empty subjects.

00:01:40.840 --> 00:01:44.140
The first big benefit is the memory management.

00:01:44.140 --> 00:01:48.700
Vector will de‑allocate memory from the heap when it goes out of scope.

00:01:48.710 --> 00:01:51.500
So memory leaks are not a problem anymore.

00:01:51.510 --> 00:01:54.060
We don't have to use new and delete operators.

00:01:54.740 --> 00:01:58.010
The name for this class is not inspired by a concept of a

00:01:58.010 --> 00:02:00.910
mathematical vector; it is just the name that library

00:02:00.910 --> 00:02:03.980
developers chose to avoid using the word array,

00:02:03.980 --> 00:02:07.110
because until the introduction of standard arrays,

00:02:07.110 --> 00:02:10.460
array would usually mean a raw C‑style array.

00:02:11.440 --> 00:02:15.010
Now let's initialize these three subjects with some values

00:02:15.010 --> 00:02:18.070
by using the square brackets operator.

00:02:18.070 --> 00:02:20.860
Vectors can be used just like standard arrays.

00:02:21.400 --> 00:02:25.190
You can use the square brackets operator or the at function to

00:02:25.190 --> 00:02:27.760
access the elements from the internal array.

00:02:28.440 --> 00:02:30.130
Let's keep this as simple as possible.

00:02:30.140 --> 00:02:32.560
I don't care about these DNA sequences anymore.

00:02:32.560 --> 00:02:35.350
So you can pass any sequence you want in here.

00:02:35.360 --> 00:02:39.520
We will only focus on working with subject IDs; they will help

00:02:39.520 --> 00:02:42.150
us in identifying one subject from another.

00:02:42.940 --> 00:02:46.850
Now I want to check if these subjects were initialized successfully.

00:02:46.860 --> 00:02:51.160
So I will pass the whole vector to the printSubjectIds function.

00:02:51.540 --> 00:02:55.460
Of course, we need to define this function first, so let's do that.

00:02:56.240 --> 00:02:58.910
I will pass the vector as a constant reference,

00:02:58.910 --> 00:03:01.360
because I don't want to make a local copy.

00:03:02.640 --> 00:03:05.250
Notice that we don't have to template this function,

00:03:05.250 --> 00:03:08.080
because the size of the vector is not important here.

00:03:08.080 --> 00:03:11.210
We don't have to provide it as a template argument.

00:03:11.210 --> 00:03:15.830
Vectors will remember their size, even in the scope of another function.

00:03:15.840 --> 00:03:19.150
So the size function, which gives us the number of elements,

00:03:19.160 --> 00:03:21.360
is also available here.

00:03:21.360 --> 00:03:23.490
But we won't need it here,

00:03:23.490 --> 00:03:28.360
because I will use a range‑based for loop to print the ID of each element.

00:03:29.040 --> 00:03:32.630
Notice that I'm using this iterator variable as a reference.

00:03:32.630 --> 00:03:36.060
We learned in the previous lesson that this is more efficient.

00:03:36.840 --> 00:03:39.860
Okay, it is time to compile this to see what we get.

00:03:40.640 --> 00:03:44.080
We already know what these first three lines do.

00:03:44.080 --> 00:03:47.350
After that, we have a parameterized constructor,

00:03:47.350 --> 00:03:50.080
followed by a move assignment operator,

00:03:50.080 --> 00:03:53.560
and this actually happens three times in a row.

00:03:53.570 --> 00:03:55.150
So what's going on?

00:03:55.540 --> 00:03:55.940
Well,

00:03:55.940 --> 00:03:59.420
these parameterized constructors are actually called when we

00:03:59.420 --> 00:04:02.650
instantiate a new subject in this main function.

00:04:03.040 --> 00:04:04.320
Once the subject is created,

00:04:04.320 --> 00:04:07.660
we assign it to the specific subject from the vector.

00:04:08.340 --> 00:04:12.870
This is an assignment operator, and since this expression is a prvalue,

00:04:12.880 --> 00:04:16.760
the move assignment will be used instead of a copy assignment.

00:04:17.240 --> 00:04:18.550
And that's great.

00:04:18.560 --> 00:04:22.140
Imagine if we didn't define move semantics; then each one of these

00:04:22.140 --> 00:04:25.490
subjects would make a deep copy to the object on the vector.

00:04:26.140 --> 00:04:28.860
So once all of these subjects are moved from the

00:04:28.860 --> 00:04:30.550
main function scope to the heap,

00:04:30.550 --> 00:04:34.750
we can see that objects on the vector are now correctly initialized,

00:04:36.240 --> 00:04:39.410
but vectors are much more powerful than simple,

00:04:39.410 --> 00:04:41.250
dynamically allocated arrays.

00:04:41.740 --> 00:04:43.860
Let's say that in the middle of the program,

00:04:43.860 --> 00:04:46.940
we allow the user to pick a new size for the array,

00:04:46.940 --> 00:04:50.150
or maybe we just have a need to store more subjects.

00:04:50.150 --> 00:04:53.870
Vectors can solve this problem, because they are resizeable.

00:04:54.400 --> 00:04:57.660
We can use the resize function to make this vector longer.

00:04:58.340 --> 00:04:59.500
Once I do this,

00:04:59.500 --> 00:05:03.160
the vectors should be able to store five elements instead of three.

00:05:03.540 --> 00:05:05.250
But you have to be careful with this,

00:05:05.250 --> 00:05:08.130
because the internal array managed by the vector

00:05:08.130 --> 00:05:10.050
did not magically become bigger.

00:05:10.440 --> 00:05:12.750
Let me compile this to show you.

00:05:12.750 --> 00:05:18.140
We are interested in this part of the output, after the list of subject IDs.

00:05:18.140 --> 00:05:21.370
You can see that after we resize the vector,

00:05:21.370 --> 00:05:24.510
five different constructors were used in the process.

00:05:24.510 --> 00:05:27.140
As I said, this is not magic.

00:05:27.140 --> 00:05:31.470
The vector will allocate a new array on the heap with the bigger size,

00:05:31.470 --> 00:05:34.260
in this case, the array with five elements.

00:05:34.640 --> 00:05:37.960
Since this array has two more elements than the previous one,

00:05:37.970 --> 00:05:41.030
it will use a default constructor to create two new

00:05:41.030 --> 00:05:43.250
subjects at the back of the array.

00:05:44.040 --> 00:05:44.830
After that,

00:05:44.830 --> 00:05:48.340
it will move all of the subjects from the previous array to

00:05:48.340 --> 00:05:50.900
the same position inside of the new array,

00:05:50.900 --> 00:05:54.870
and then the old array will be de‑allocated from the heap.

00:05:54.880 --> 00:05:56.980
We are only left with this new one.

00:05:56.990 --> 00:06:00.830
This is why this list has two new subjects with the ID of 0.

00:06:02.740 --> 00:06:06.400
It's great that we defined move semantics for the Subject class,

00:06:06.400 --> 00:06:07.630
because if we didn't,

00:06:07.630 --> 00:06:11.650
this would make a deep copy of three subjects from the previous array.

00:06:12.140 --> 00:06:16.850
Each subject has 60MB of memory allocated for the DNA sequence,

00:06:16.850 --> 00:06:19.860
which means that this resizing alone would cost us the

00:06:19.860 --> 00:06:25.560
performance of allocating 180MB of new memory and making a copy

00:06:25.560 --> 00:06:28.060
from the old memory to fill that space.

00:06:29.040 --> 00:06:32.300
You can now see how the move constructor is a really important

00:06:32.300 --> 00:06:35.960
part of defining classes with dynamic resources.
