1 00:00:05,250 --> 00:00:09,090 In the last video we learned about stateless lambda expressions. 2 00:00:09,090 --> 00:00:13,650 That is, lambda expressions that capture no information from their environment. 3 00:00:14,620 --> 00:00:19,180 In this video, we'll learn about their close relative, the stateful lambda expression. 4 00:00:19,630 --> 00:00:24,100 That is a lambda expression that does capture information from its environment. 5 00:00:24,670 --> 00:00:30,220 It's important to note that stateful lambda expressions are just like stateless lambda expressions, 6 00:00:30,220 --> 00:00:32,890 except they have non empty capture lists. 7 00:00:32,890 --> 00:00:37,330 So everything we do with the stateless lambda, we can do with a stateful lambda and more. 8 00:00:37,360 --> 00:00:42,970 So what exactly do we mean when we refer to a lambda capturing information from its environment and 9 00:00:42,970 --> 00:00:44,350 how is it able to do this? 10 00:00:44,950 --> 00:00:51,130 Well, what we're referring to is the lambda ability to use variables declared within its reaching scope 11 00:00:51,130 --> 00:00:54,430 without having to pass them into the lambda as parameters. 12 00:00:55,190 --> 00:01:00,560 This is accomplished by simply listing the variables we would like the lambda to use within its capture 13 00:01:00,560 --> 00:01:01,160 list. 14 00:01:01,190 --> 00:01:02,270 Pretty cool, right? 15 00:01:02,270 --> 00:01:03,680 But how does it work? 16 00:01:03,740 --> 00:01:09,260 Well, to fully understand this, we first need to take a look under the hood to see what happens when 17 00:01:09,260 --> 00:01:11,030 a lambda expression is compiled. 18 00:01:12,360 --> 00:01:17,650 Here we can see a simple stateless lambda expression defined to represent the lambda. 19 00:01:17,670 --> 00:01:23,520 The compiler generates what's known as a closure type class with a default constructor and an operator 20 00:01:23,520 --> 00:01:24,030 function. 21 00:01:24,030 --> 00:01:26,010 Implementing the logic of the lambda. 22 00:01:26,040 --> 00:01:31,980 The class isn't generated until compile time, so it might now be clear why the auto keyword must be 23 00:01:31,980 --> 00:01:35,100 used is to specify the for the type and lambdas. 24 00:01:35,610 --> 00:01:39,900 It's because when we define lambda expressions, the type hasn't been generated yet. 25 00:01:40,810 --> 00:01:46,510 The type is only generated when the lambda is compiled and so of course can only be assigned by the 26 00:01:46,510 --> 00:01:47,980 compiler at compile time. 27 00:01:48,250 --> 00:01:52,600 With this in mind, can you see what's happening when we assign a land expression to a variable? 28 00:01:53,020 --> 00:01:59,410 What we're actually doing is instantiating an object of the compiler generated closure by making a call 29 00:01:59,410 --> 00:02:00,640 to its constructor. 30 00:02:01,210 --> 00:02:05,320 Hopefully now you'll have a better understanding of how lambdas operate behind the scenes. 31 00:02:05,320 --> 00:02:10,270 But that still leaves the question of how they can capture information from their environment using 32 00:02:10,270 --> 00:02:13,000 the capsule list as the challenge. 33 00:02:13,000 --> 00:02:18,340 Positive video now and see if you can figure it out with your new knowledge of how lambdas work when 34 00:02:18,340 --> 00:02:18,760 you're done. 35 00:02:18,760 --> 00:02:21,520 Unpause the video and we'll go through it in the next slide. 36 00:02:25,800 --> 00:02:31,140 If you thought of storing the captured variables as member variables of the compiler generated closure, 37 00:02:31,440 --> 00:02:33,060 then you were absolutely right. 38 00:02:33,540 --> 00:02:39,750 When defining a stateful lambdas capture list where defining the parameterized constructor of the lambdas 39 00:02:39,750 --> 00:02:45,180 compiler generated closure when the state for Lambda Expression is instantiated. 40 00:02:45,360 --> 00:02:51,480 A unique function object is created using the parameterized constructor, which stores the captured 41 00:02:51,480 --> 00:02:53,790 variables as member variables. 42 00:02:54,690 --> 00:02:56,910 We can see this being done in the example. 43 00:02:57,760 --> 00:03:03,670 A simple stateful lambda expression is defined which captures the local variable Y and takes a single 44 00:03:03,670 --> 00:03:04,870 parameter x. 45 00:03:05,530 --> 00:03:11,860 The compiler generates a closure for the lambda with a parameterized constructor that takes as its parameter 46 00:03:11,860 --> 00:03:16,540 the variable y and assigns it to the closures member variable y. 47 00:03:16,570 --> 00:03:21,820 You'll notice that the generated closure has an operator function implementing the logic of the lambda 48 00:03:21,820 --> 00:03:23,090 as we would expect. 49 00:03:23,110 --> 00:03:25,990 However, this time it's a constant member function. 50 00:03:26,470 --> 00:03:32,170 This means that no member variable of the instantiated object can be modified by this function, and 51 00:03:32,170 --> 00:03:35,230 so the member variable y cannot be modified. 52 00:03:35,930 --> 00:03:42,200 The reason for this is because by default, all variables captured by value are captured by contract 53 00:03:42,200 --> 00:03:42,800 value. 54 00:03:43,670 --> 00:03:48,500 As you can imagine, this can be quite restricting when we're trying to implement certain functionalities. 55 00:03:48,500 --> 00:03:54,030 So C++ provides us with a multitude of ways in which we could capture variables. 56 00:03:54,050 --> 00:03:55,460 Let's take a look at them. 57 00:03:56,320 --> 00:03:57,760 As seen in the last example. 58 00:03:57,760 --> 00:04:02,530 The first way in which a lambda expression can capture a variable is by value. 59 00:04:02,650 --> 00:04:07,570 This is the default capturing mode, and so it can be accomplished by simply listing the variables. 60 00:04:07,570 --> 00:04:09,670 Name in the lambdas capsule list. 61 00:04:10,510 --> 00:04:16,269 It's important to remember that a variable being captured by value is actually being captured by cost 62 00:04:16,269 --> 00:04:19,990 value, so it won't be modifiable within the lambda. 63 00:04:20,260 --> 00:04:24,730 But what if we want to capture a variable by value and modify it within the lambda? 64 00:04:26,760 --> 00:04:32,130 In that case, we can use the keyword mutable to tell the compiler to generate the lambdas operator 65 00:04:32,130 --> 00:04:35,550 function as a non const member function. 66 00:04:35,820 --> 00:04:41,040 By doing so, we can capture variables by value and modify them within the lambda. 67 00:04:42,120 --> 00:04:45,510 As you might have guessed, we can also capture variables by reference. 68 00:04:46,140 --> 00:04:51,660 In this case, any changes made to a variable captured by reference within the lambda will be visible 69 00:04:51,660 --> 00:04:53,010 outside the lambda. 70 00:04:53,800 --> 00:04:58,960 Using both capturing modes, we can define a lambdas capsule list any number of ways for any number 71 00:04:58,960 --> 00:04:59,800 of variables. 72 00:05:00,070 --> 00:05:05,560 But what if we want to capture a large number of variables, but we don't want to have to list each 73 00:05:05,560 --> 00:05:06,280 variable. 74 00:05:06,310 --> 00:05:07,570 How do we do this? 75 00:05:09,350 --> 00:05:11,510 This is where default captures come in. 76 00:05:12,050 --> 00:05:17,630 A default capture allows the lambda to capture all variables referenced within its body according to 77 00:05:17,630 --> 00:05:19,250 the defined capture mode. 78 00:05:20,610 --> 00:05:26,280 An equal sign positioned first in the lambdas capsule list denotes that all referenced variables should 79 00:05:26,280 --> 00:05:27,870 be captured by value. 80 00:05:29,270 --> 00:05:32,600 An ampersand denotes that they should be captured by reference. 81 00:05:33,760 --> 00:05:39,400 And if we use the this keyword, this denotes that the referenced member variables of the current object, 82 00:05:39,400 --> 00:05:43,180 the lambda is defined within should be captured by reference. 83 00:05:45,120 --> 00:05:50,940 When implementing default captures, we can also explicitly capture variables according to different 84 00:05:50,940 --> 00:05:51,990 capture modes. 85 00:05:52,650 --> 00:05:58,050 It's important to note that when we do so, we must always place the default capture first in the capture 86 00:05:58,080 --> 00:05:58,650 list. 87 00:05:59,160 --> 00:06:02,970 Also, the explicit capture cannot be the same as the default. 88 00:06:03,000 --> 00:06:05,010 Otherwise the lender won't compile. 89 00:06:05,900 --> 00:06:11,450 With so many possible combinations of default and explicit parameters, it's hard to cover them all. 90 00:06:11,720 --> 00:06:15,980 But what we've covered should prepare you for most situations in which you will need to use stateful 91 00:06:15,980 --> 00:06:16,730 lambdas. 92 00:06:17,000 --> 00:06:19,730 Now let's head over to the IDE and implement some.