WEBVTT

00:01.560 --> 00:06.450
Hello again! In this video, we're going to look at the array, string and vector in C++.

00:08.620 --> 00:14.320
We'll start with the array. This is a block of contiguous memory, so this means that you have a block

00:14.320 --> 00:18.460
of memory with elements, all one after the other, with no gaps in between them.

00:19.510 --> 00:24.010
This block is indexed, so there are numbers zero one, two three and so on.

00:24.940 --> 00:28.120
For some reason, computer programmers always start counting things from zero.

00:28.990 --> 00:36.010
So if you say I want the element at index 17, then the program will jump straight to that.

00:36.430 --> 00:37.660
And it's a very fast and efficient

00:37.660 --> 00:43.060
way of accessing memory. And modern hardware is actually optimized to work with this kind of structure.

00:44.710 --> 00:48.040
Arrays came from C, so they're a bit basic.

00:49.390 --> 00:54.700
We can allocate an array on the program stack, so we can have a local variable, which is an array, and gets

00:54.700 --> 00:56.020
destroyed at the end of scope.

00:56.710 --> 01:02.560
But to do that, the array has to have a fixed number of elements, and you have to know in advance how many

01:02.560 --> 01:03.610
elements you're going to have.

01:04.570 --> 01:09.130
So you can create an array which has five elements because the number five is known in advance.

01:10.180 --> 01:19.390
If you want to use a variable, that won't work in standard C++, unless the variable is a constant. And for aconstant,

01:19.390 --> 01:20.530
it has to be initialized.

01:20.950 --> 01:26.830
So the compiler will know what value it has. There is actually an extension in Gnu C++, which does

01:26.830 --> 01:28.950
allow this, which is rather annoying.

01:29.350 --> 01:29.650
Even

01:29.650 --> 01:32.200
if you say you want standard C++, it still does it.

01:32.650 --> 01:34.630
You have to say you're being pedantic to turn it off.

01:36.400 --> 01:39.250
I think the reason for that is you are actually allowed to do that in C.

01:39.250 --> 01:43.780
But the implementation in C is a bit of a hack, which is why C++ hasn't adopted it.

01:47.370 --> 01:52.140
We can also have a dynamic array, which means that the memory is allocated on the heap.

01:52.740 --> 01:56.880
And if we don't know the number of elements in advance, then we have to do that.

01:57.300 --> 02:02.370
Or if we want to be able to vary the number of elements, then we have to use a dynamic array as well.

02:03.120 --> 02:10.880
And to do this, we use the new operator. And then after the type, we put the number of elements in

02:10.890 --> 02:11.760
square brackets.

02:12.180 --> 02:17.610
So this will allocate enough memory to hold that number of ints, and it'll return a pointer to

02:17.610 --> 02:19.140
the start of the allocated memory.

02:19.800 --> 02:21.930
And then we can store this in this address,

02:22.260 --> 02:23.580
pArr.

02:25.340 --> 02:32.690
And then that memory will be allocated for the program until we explicitly release it or if the program

02:32.690 --> 02:37.700
finishes, then usually the program will go and release the memory before the program actually exits.

02:39.650 --> 02:45.050
To release the memory, we need to call delete and we must give the form that uses square brackets. So

02:45.050 --> 02:49.760
there's actually two forms of new and delete, one which doesn't have square brackets and one which does.

02:50.030 --> 02:54.560
And you must not get them mixed up as otherwise bad things will happen.

02:56.490 --> 03:02.070
So this will take the address of the start of the memory block, and it'll release all the memory that

03:02.070 --> 03:05.160
was allocated by the corresponding call to new.

03:09.710 --> 03:12.350
C has a rather rudimentary form of strings.

03:12.980 --> 03:15.050
It's an array of constant char.

03:16.070 --> 03:20.110
Each character in the string is stored as an element in the array, so we have something like this.

03:20.120 --> 03:23.420
So there's the array, the block of contiguous memory.

03:24.020 --> 03:27.020
Then each element in this array has a single character.

03:27.650 --> 03:33.640
And then at the end of that, there's a null character, which has the value zero. Not the character

03:33.650 --> 03:36.350
zero, the actual number value zero.

03:36.890 --> 03:41.000
These are all stored as codes, which represent different characters.

03:42.620 --> 03:47.900
And then if you use C functions to manipulate these, these will look for the terminating null.

03:48.410 --> 03:51.590
So they're rather slow, because they have to look all the way through the string.

03:52.130 --> 03:57.890
And also, if the null isn't there or it gets lost or put in the wrong place, then all sorts of disasters

03:57.890 --> 03:58.370
can happen.

03:58.880 --> 04:00.140
So this is not terribly safe.

04:01.670 --> 04:05.720
When we have a string literal, this is actually a C style string.

04:06.560 --> 04:07.820
So if we have...

04:09.360 --> 04:09.810
(Excuse me)

04:10.140 --> 04:17.550
If we have an expression like this, then the array will be allocated for you.

04:18.510 --> 04:23.550
So that's equivalent to making an array of const char, which has those letters as the elements and it's

04:23.550 --> 04:24.510
null terminated.

04:26.010 --> 04:27.960
So this is all stuff that's inherited from C.

04:31.360 --> 04:37.480
In C++, we have a standard string, this is actually part of the C++ library, not the core language.

04:38.470 --> 04:40.000
So this is a class.

04:40.840 --> 04:45.490
The class has a member, which is a dynamic array, so it has memory, which is allocated on the heap

04:46.180 --> 04:47.230
to store the elements.

04:48.450 --> 04:52.720
And it also has another member which keeps count of how many elements there are in the string.

04:53.530 --> 04:54.790
So it'll look a bit like this.

04:55.690 --> 04:57.130
So we have the string class.

04:57.640 --> 05:02.020
It has a pointer to characters which stores the data.

05:02.020 --> 05:07.690
So that's the block of contiguous memory, and it also has a member, which stores the number of elements.

05:08.380 --> 05:12.430
So you can think of this as being a bit like an array which manages itself.

05:13.360 --> 05:17.530
So it's a kind of object oriented string, as opposed to the procedural string in C.

05:23.430 --> 05:28.480
So objects of this class, the standard string, they behave like a dynamic array, so they allocate

05:28.500 --> 05:30.120
memory on the heap and it gets released.

05:30.600 --> 05:32.190
But we can use them like a local variable.

05:32.910 --> 05:39.030
So if we create a variable, which is a string, the constructor for this will allocate storage on the

05:39.030 --> 05:42.240
heap and it'll populate it with this data.

05:43.230 --> 05:47.450
And then when the program gets to the end of the scope, the destructor for the string will be called.

05:47.860 --> 05:49.500
That will release the memory.

05:54.770 --> 05:56.300
(Should really use shorter sentences!)

05:58.100 --> 06:03.050
The class also has special member functions for handling, copying and assigning objects, so that's the

06:03.050 --> 06:05.330
copy constructor and the assignment operator.

06:06.020 --> 06:11.420
And this will make sure that these are handled correctly by allocating a new block of memory when needed.

06:12.440 --> 06:17.370
And if we change the size of the string, if we decide to change that to "hello, world".

06:17.420 --> 06:22.880
So we need extra storage than the string class will automatically allocate the extra memory and make

06:22.880 --> 06:27.200
sure that the data is correctly populated, so it makes life a lot easier.

06:31.830 --> 06:36.280
We can use these same subscription notation with strings that we use with arrays, so we just put a

06:36.280 --> 06:38.160
[square] bracket with the index of the element

06:38.160 --> 06:42.600
we want. The elements are indexed the same way, starting with zero as usual.

06:43.350 --> 06:47.790
And it also has a size member function which returns the number of elements.

06:52.440 --> 06:56.940
If we could look at a string in memory, we'd see something that might be a bit like this.

06:58.260 --> 07:05.550
So there's the actual string object, so it has this pointer to the data and this member which has the

07:05.550 --> 07:06.310
number of elements.

07:07.290 --> 07:11.130
And then this pointer will be pointing to some address in memory somewhere.

07:11.520 --> 07:14.850
And this memory block will store the actual data for the string.

07:21.300 --> 07:26.040
We also have a standard vector, which is similar to a string, but the difference is that in a string

07:26.550 --> 07:28.380
the elements have to be characters.

07:29.100 --> 07:31.140
In a vector, it can be any type you want.

07:32.040 --> 07:35.660
So we could, for example, create a vector of ints and do that.

07:35.720 --> 07:40.920
We put "int" in angle brackets after the word vector, and that's known as a type parameter.

07:41.160 --> 07:46.530
So in this, we're creating a vector of ints, and we're using this list initialization that we saw before.

07:47.160 --> 07:50.190
So we're creating a vector of ints with the values four two three five one.

07:54.760 --> 07:58.870
So it's a similar structure to the string. We have a member which is a dynamic array but it's going to be

07:58.870 --> 08:01.540
a type which is the same as the parameter.

08:01.540 --> 08:07.030
So in this case, we're going to have a block if ints, so this is going to be pointer to int. And and we have

08:07.030 --> 08:08.080
the size member again.

08:12.210 --> 08:18.830
And similarly, we can use subscript notation to get data using an index so we can get an element's data.

08:19.590 --> 08:25.290
There's a size member function which returns the number of elements and there's a push back in the function,

08:25.770 --> 08:28.230
which will add a new element at the back of the vector.

08:29.040 --> 08:33.810
So if we have our vector with these elements, then we call push_back.

08:35.220 --> 08:41.130
The class will add the element six at the back of the vector. If it needs more memory, it will allocate it.

08:44.650 --> 08:47.950
And the vector in memory looks very similar to the string.

08:50.240 --> 08:55.610
And here we can see we're doing a push_back operation, so the element six is being added at the back of

08:55.610 --> 08:56.120
the vector.

08:59.180 --> 09:01.160
OK, so that's it for this video.

09:01.640 --> 09:04.610
I'll see you next time, but meanwhile, keep coding!
