WEBVTT

00:00.150 --> 00:03.870
Hello again! In this video, we are going to look at insert iterators.

00:05.430 --> 00:07.710
We have already met stream iterators.

00:08.130 --> 00:11.250
If you assign to an output stream iterator,

00:11.550 --> 00:14.730
this will insert data into the corresponding output stream.

00:15.630 --> 00:20.850
The library also provides us with insert iterators. If we assign to one of these,

00:21.090 --> 00:24.480
it will insert an element into the associated container.

00:26.870 --> 00:30.290
There are three types of iterator which can add at different places.

00:30.710 --> 00:35.720
One for the back, one of the front, and one which will insert at any given position.

00:39.630 --> 00:43.710
To get an insert iterator, we need to call an inserter function.

00:44.190 --> 00:48.960
And there is one of these for each of the iterators: back, front and arbitrary.

00:49.890 --> 00:52.860
The arguments to the inserter call is the container.

00:53.250 --> 00:59.130
The container object that we wish to insert the element into. And the function will return an insert

00:59.130 --> 01:02.070
iterator, which is bound to that particular object.

01:04.790 --> 01:10.400
The back insert iterator will add a new element at the back of the container. It will call the

01:10.420 --> 01:12.200
push_back() function of the container.

01:12.560 --> 01:17.360
So, obviously, this only works with containers that supports push back, and not all of them do.

01:18.770 --> 01:22.670
The value that we are assigning will be passed as the argument to push_back().

01:23.660 --> 01:28.700
So every time we assign to this iterator, a new element will be added at the back of the container.

01:29.090 --> 01:32.000
And its value will be the value that we are assigning to it.

01:32.900 --> 01:36.020
So here is an example. We start off with an empty vector.

01:36.890 --> 01:38.680
Then we get a back insert

01:38.690 --> 01:45.900
iterator for it. We call back_inserter() with the vector object as argument. And that will return a back

01:45.920 --> 01:46.440
insert

01:46.460 --> 01:47.020
iterator.

01:48.400 --> 01:55.570
And then when we assigned to it, say 99, this will call push_back() on the vector with argument 99. If we

01:55.660 --> 01:59.140
assign again, with 88, it will call push_back() again, with argument 88.

01:59.740 --> 02:03.430
So we should have a vector with two elements which are 99 and 88.

02:05.830 --> 02:06.670
And that is what we get.

02:06.700 --> 02:08.200
So we have the empty vector.

02:08.620 --> 02:10.600
We get a back insert iterator.

02:10.690 --> 02:11.530
We assign to it.

02:12.130 --> 02:13.600
And that populates the vector.

02:15.070 --> 02:19.360
The front insert iterator is exactly the same, except it calls push_front().

02:20.140 --> 02:23.650
Unfortunately, we do not know any containers yet, which support push_front().

02:24.130 --> 02:25.780
Vector and string do not support it.

02:26.440 --> 02:30.610
But if you know how to use the list or deque types, then you can try that for yourself.

02:32.200 --> 02:36.430
With the inserter function, we need to provide a second argument, which is the position where

02:36.430 --> 02:38.650
we want to insert the new element.

02:39.490 --> 02:44.860
And that is just a normal positional iterator. So we can do something like this to get the second element.

02:44.860 --> 02:46.420
An iterator to the second element.

02:47.350 --> 02:51.040
Then we can pass that as the second argument to the inserter call.

02:52.270 --> 02:54.280
And obviously the vector is the first argument.

02:54.970 --> 03:01.510
And this will return an insert iterator, which will insert an element before the second element

03:01.510 --> 03:02.170
of this vector.

03:03.520 --> 03:06.610
So we have a vector with elements 1, 2 and 3.

03:07.960 --> 03:14.140
We get a positional iterator to the second element of this vector, and then we pass that as the second

03:14.140 --> 03:15.880
argument to the inserter call.

03:16.450 --> 03:18.340
And obviously, the vector is the first argument.

03:19.120 --> 03:24.760
Then, when we assign to this iterator, this will call the insert member function of the vector with

03:24.940 --> 03:28.720
the position as the first argument and the value 99 as the second argument.

03:29.380 --> 03:33.880
So this will insert a new element, with value 99, just before this

03:33.910 --> 03:34.510
iterator.

03:34.870 --> 03:37.570
So that is going to go just before the second element.

03:39.280 --> 03:43.090
And then the elements of the vector will be 1, 99, 2 and 3.

03:46.420 --> 03:46.800
OK.

03:47.620 --> 03:52.600
One thing we need to be careful of. And this applies to insert operations generally, not just with iterators.

03:54.510 --> 04:00.000
Looking at this code again, we have this iterator to the second element, and then we insert something

04:00.000 --> 04:00.540
before it.

04:01.110 --> 04:06.090
So after we do this insertion, what is the status of this iterator?

04:06.870 --> 04:10.620
And the answer is that it is undefined. It is possibly invalid.

04:11.100 --> 04:16.260
The reason is that the vector it may have done some internal rearrangement. It may have moved the elements

04:16.260 --> 04:17.970
around or relocated the buffer.

04:18.870 --> 04:22.860
So I am going to dereference it and print the results out. And let's see what happens.

04:25.870 --> 04:27.700
So you can see, there was a bit of a pause there.

04:27.970 --> 04:29.860
And I think that was because the program has crashed.

04:30.460 --> 04:31.900
When I did this with gcc,

04:31.900 --> 04:33.730
I just got completely random numbers.

04:34.300 --> 04:36.670
So obviously it's not safe to use that iterator.

04:38.650 --> 04:44.230
So if you have an insert operation, then any iterators or references to elements which you took before

04:44.230 --> 04:48.910
the insert operation. [They] are no longer valid and you should not use them.

04:50.000 --> 04:56.360
We can use insert iterators anywhere that expects a positional iterator. One use is with algorithms which

04:56.360 --> 04:56.780
copy iterators.

04:57.260 --> 04:59.300
So we talked about this with output streams.

04:59.660 --> 05:04.370
You can provide an output stream iterator and it will copy the container to output.

05:05.510 --> 05:08.810
With this one, it'll copy the container to a different container.

05:09.650 --> 05:15.710
The advantage of using an insert iterator is that the container will always expand to make sure

05:15.710 --> 05:16.580
it has enough room.

05:17.300 --> 05:23.090
If you just use an ordinary iterator, then you may overflow the container. But we will look at that

05:23.210 --> 05:26.030
in more detail, when we go into copying algorithms.

05:27.920 --> 05:33.800
Another use for insert iterator is with stream iterators. So you can write much simpler code for

05:34.310 --> 05:36.500
copying data from input into a container.

05:37.580 --> 05:41.180
So let's remind ourselves how input stream iterators work.

05:41.630 --> 05:47.000
We have an input stream iterator, which is bound to the standard input, and we have another one

05:47.000 --> 05:47.930
which is empty.

05:49.370 --> 05:53.120
Then we have this loop, so we compare the two iterators.

05:53.810 --> 05:55.880
If they are different, then there is more input.

05:56.300 --> 06:00.230
If they are the same, then we have reached the end of inputs and we can terminate our loop.

06:01.280 --> 06:06.710
Then we dereference the input stream iterator. And that will give us the next bit of data from the

06:06.710 --> 06:12.320
inputs. And then we increment the iterator to move on to the next word in the input.

06:15.040 --> 06:20.170
Here we have a back insert iterator to a vector. So we have our empty vector and we have the

06:20.500 --> 06:24.580
call to back inserter. And that is a back insert iterator.

06:25.090 --> 06:31.690
So if we assign to that iterator, it will call push_back() on the vector. And it will append the data

06:31.810 --> 06:33.070
to the back of the vector.

06:34.150 --> 06:38.470
So this is reading data from the stream and appending it to the back of the vector.

06:39.940 --> 06:45.280
And then when we reach the end of the loop, the data in the vector should be the same as the data

06:45.280 --> 06:46.570
that was typed in at the keyboard.

06:46.900 --> 06:47.710
So let's try this.

06:55.530 --> 06:58.620
So... a bit of input. And there we are.

06:59.580 --> 07:04.800
So the data that I entered in the keyboard goes straight into the vector. And that is probably a bit

07:04.800 --> 07:08.400
simpler than using right-shift operators and calling push_back() directly.

07:10.870 --> 07:12.460
OK, so that is it for this video.

07:12.910 --> 07:15.910
I'll see you next time, but until then, keep coding!
