WEBVTT

00:00.180 --> 00:00.750
Hello again!

00:01.080 --> 00:06.510
In this video, we are going to look at lvalues and rvalues. In C++,

00:06.510 --> 00:09.480
every object is either an lvalue or an rvalue.

00:10.440 --> 00:13.890
This is something that actually goes back to the ancestors of C.

00:14.610 --> 00:16.650
And, originally, it was very simple.

00:17.370 --> 00:24.090
If you have something which can appear on the left of an equal sign, that is an lvalue. "L" for "left".

00:25.380 --> 00:30.840
If you have something which can only appear on the right of an equals sign, then that is an rvalue.

00:31.560 --> 00:32.520
"R" for "right".

00:33.480 --> 00:35.970
So, for example, we can say "x equals 2".

00:36.000 --> 00:40.560
So x is an lvalue. But we cannot say "2 equals something".

00:41.250 --> 00:42.960
So 2 is an rvalue.

00:44.310 --> 00:51.000
And also, with the return value from a function call. We can say that "x equals the return value", but

00:51.000 --> 00:51.600
we cannot say

00:51.600 --> 00:53.790
"the return value is equal to something."

00:54.270 --> 00:56.760
So the function return value is an rvalue.

00:58.950 --> 01:03.120
Unfortunately, this rule is not sufficient for C++.

01:03.840 --> 01:10.170
In C++ we have overloaded operators, and some operators can return things which can be assigned to.

01:11.040 --> 01:17.580
So we need a different rule. In C++, an lvalue represents a named memory location.

01:18.330 --> 01:22.380
So the variable must have a name, and we must be able to take its address.

01:23.370 --> 01:29.820
So to be an lvalue, it must have a name, and we must be able to get the address of this, by using

01:29.820 --> 01:31.590
the address-of operator.

01:32.430 --> 01:40.110
So for example, with x, that has a name, x. And we can take the address of it using the address-of operator.

01:40.440 --> 01:42.180
So X is an lvalue.

01:45.620 --> 01:47.390
Everything else is an rvalue.

01:47.990 --> 01:54.350
So for example, 2 does not have a name, and we cannot take its address the person value.

01:54.470 --> 01:57.770
And the return value from function does not have a name, and we cannot take its address.

01:58.190 --> 01:59.570
So those are both rvalues.

01:59.960 --> 02:02.630
So we have a more complex rule, but it does give the same answers.

02:04.190 --> 02:10.880
The reason why all this is important is that lvalues and rvalues can behave differently when we

02:10.880 --> 02:12.950
pass them as function arguments.

02:18.880 --> 02:20.050
With pass by value,

02:20.050 --> 02:21.910
it does not actually make any difference.

02:22.390 --> 02:29.320
If we have some function which takes an int by value, we can pass an lvalue, a variable x or we can pass

02:29.320 --> 02:31.990
an rvalue: an int literal 2.

02:33.880 --> 02:36.940
However, if we are passing by address, then it does make a difference.

02:37.630 --> 02:43.390
We can pass an lvalue, because we can take the address of an lvalue, but we cannot pass an rvalue,

02:43.690 --> 02:46.150
because we cannot take the address of an rvalue.

02:48.760 --> 02:49.900
And passing by reference.

02:49.900 --> 02:52.240
This is really another way of taking the address.

02:52.570 --> 02:53.740
So again, we have the same rule.

02:54.010 --> 02:55.840
We can pass lvalues by reference.

02:56.170 --> 03:02.590
That is a non-const reference by the way. But we cannot pass rvalues by non-const reference.

03:05.020 --> 03:06.280
So there is some logic to this.

03:06.290 --> 03:11.980
If we are passing by address or by non-const reference, that usually means we want to modify the

03:11.980 --> 03:15.860
argument and modifying an rvalue does not really make much sense.

03:16.450 --> 03:17.650
So that is why it is not allowed.

03:20.280 --> 03:26.430
If we have passing by reference to const, then that is sort-of like passing by value.

03:26.850 --> 03:29.190
So we have the same rules as for pass by value.

03:31.140 --> 03:33.540
So let's actually look at the example in the compiler.

03:36.780 --> 03:39.450
Here, we have a function which returns an int.

03:40.110 --> 03:43.890
So if we call this function, the object we get will be an rvalue.

03:45.030 --> 03:48.360
The return value has no name, and we cannot take its address.

03:49.800 --> 03:54.000
We have another function which takes its argument by reference to const int.

03:55.170 --> 04:02.160
So if we call this function, and we pass the rvalue that we get by calling this function, what will happen?

04:03.030 --> 04:03.840
Is this legal?

04:06.610 --> 04:09.820
And the answer is yes, it is legal. It compiles and runs.

04:11.020 --> 04:15.190
So you can actually pass an rvalue by reference to const, as well as by value.

04:17.150 --> 04:18.480
In C++, we

04:18.530 --> 04:26.990
so far know about pass by value, pass by reference - const and non-const - and pass by address. In

04:26.990 --> 04:27.310
C++11,

04:27.320 --> 04:34.290
we also have pass by move. And this actually uses the same syntax as passing by value.

04:34.910 --> 04:39.890
If you write something like this in older versions of C++, this is always passed by value.

04:40.580 --> 04:43.370
The argument object is copied into the function.

04:43.760 --> 04:47.870
So the function has a local variable, which is a copy of the argument that was passed to it.

04:49.040 --> 04:55.520
If you use the same syntax in C++11, the object may be moved into the function.

04:55.970 --> 05:02.120
So the variable in the function actually has the data that used to be in the object which was passed

05:02.120 --> 05:02.810
to the function.

05:03.740 --> 05:09.710
For this to happen, the object that is passed must be an rvalue and it must have a type which can

05:09.710 --> 05:10.400
be moved.

05:10.820 --> 05:12.920
And I will tell you the rules for that later.

05:13.610 --> 05:21.080
But for now, you can do this for every library type in the C++11 class library. With a few exceptions,

05:21.080 --> 05:27.110
of course, there is always exceptions! And most exceptions are to do with thread synchronization, which we

05:27.110 --> 05:28.490
are not covering in this course.

05:30.370 --> 05:37.930
On the other hand, if the object which is passed is an lvalue, or we pass something which is not movable,

05:38.440 --> 05:43.180
and that includes built in types, then those will be copied instead.

05:43.510 --> 05:46.990
So we get exactly the same behaviour as we did before C++11.

05:48.100 --> 05:53.140
So if you have some classes and they were not written for move semantics and you pass them by value,

05:53.590 --> 05:56.140
then do not worry, that will continue to happen.

05:56.590 --> 05:59.020
So this is all completely compatible with old code.

06:00.580 --> 06:01.000
Okay.

06:01.000 --> 06:02.110
So that is it for this video.

06:02.740 --> 06:03.640
I will see you next time.

06:03.640 --> 06:05.890
But until then, keep coding!
