In this lecture, you learn about C plus plus raw pointers and although you should use C plus plus smart pointers, which we'll talk about in the next lecture almost exclusively. You're almost definitely going to run into raw pointers if you work on legacy code. In addition, some of the ideas that apply to raw pointers also apply to smart pointers. So we'll look at those in this lecture as well. The reason we use pointers, whether they're raw or smart is so that we can dynamically allocate memory as our program runs. Here's the big idea behind pointers. As you can see our age variable which is stored at memory location 40, just stores and age in this case 17. So 17 is the value of that variable. Our score variable is a pointer to an integer located somewhere else. So the value of our score variable, which is a pointer, is actually a memory address and that memory address is 44 in this particular picture. So the integer that holds the actual score is in memory location 44. And the score pointer variable, points to that location in memory. That's why they're called pointers. Let's go see how this actually works in code. Let's start by looking at declaring point of variables. Online 14 here, I'm declaring a pointer to an int, so this isn't an int. This is a pointer to an int. And I have called this pointer score and I'm initializing the value of this score pointer to be null pointer. We've seen some of this before. We've seen the Asterias when we've declared pointers in some of our unreal script and we've also seen comparisons to null pointer when we were retrieving pointers to particular objects and we wanted to make sure that the pointers weren't null before we try to access functions on those objects. So the syntax should feel familiar to you. Although we've never actually initialized our pointers this way. In our Unreal games, we've always been setting our pointer variables equal to the result from some function. We were calling in the Unreal engine, just to show you that we can point to more than the fundamental data types. I'm pointing to a die here, and I'm calling this pointer D6 because it's going to a point to a six sided die. Now, the pointer doesn't care. The pointer knows it's going to point to a die object and it doesn't care how many sides it has. But this one I'm going to call D6 and I'll also initialize that one to a null pointer. And then finally, I have a third point of variable also pointing to a die object. This one will point to a D20. But I wanted to show you that I can declare the pointer variable and create the object at points to and set the point of variable to point to that object all in one line of coat. So I've got a pointer to a die and I will construct a new die and I will call the die constructor that passes in one argument, the number of sides for the die. So I'm passing in 20 year. So score will point to an integer though it doesn't yet. It just is a null pointer. D6 will point to a die object though it doesn't yet. It's an old pointer, and D20 will point to a die object and it already does because I created a new die object and initialized this pointer to point to it with this syntax. The next thing we'll see is allocating memory. We don't need to do that for the D20 because we already allocated memory for the die. But score will allocate memory for an int, and D6 will allocate memory for a die object. And it doesn't just allocate memory. It also sets the pointer to point to the memory that was allocated. So it holds the address of the memory that is allocated for an integer or the object that it just created for a die. And of course this will be a six sided die because we called the constructor version for the die that doesn't have any parameters. So It automatically creates a six sided die for us. The next thing we'll do is a whole bunch of printing of addresses. So I print the address of score. So this is where the pointer gets stored in memory. And then I print the address that score points to and that address is where the isn't actually is located in memory. Similarly I do that for the address of D6, so the address of the pointer and then the address of the die object D6 points to, then the address of the D20 and then the address of the D20 object. The die object that the D20 pointer points to. Now we will change and print the value of the fundamental type to access the value that score points to. We need to use what's called the D reference operator. So it D references the pointer. In other words here's the pointer, but here's what the pointer points to. So I can print out the value of the int. That score points to by D referencing the pointer with this asterisk. And I can also change the value of the int that score points to by de referencing the pointer and then setting it to some value. And of course I can D reference the pointer to do math with the end and all kinds of other things. I'm just showing the assignment here. But the big idea is we D reference the pointer to actually get to the memory that the pointer points to to sort of follow that pointer and end up at where it actually points to. I can also call functions on the D6 and we will look at the arrow notation that we've seen before in unreal engine scripts. 1st I'll show you that. Another way to do It is we can D reference the D6 pointer which means we're now holding an object a die object in this case. And so we just use the dot notation to call functions on the die object. So remember when I talked about the arrow notation, I said we're used to using the dot notation to call functions on an object. But because it's a pointer will use the arrow notation instead. And that is by far the more common notation to use. So the arrow notation is here. So, another way I can call a function on an object that a pointer points to, is to put the name of the point of variable and then the arrow and then the function I'm trying to call. And we've seen this numerous times in our previous work in Unreal Engine Games. But this is another way to do the same thing, hardly anyone does that. Most programmers will use the arrow notation. So that's what we'll continue to do when we're d referencing a pointer and calling a function on the object that the pointer points to. And then I call functions on the D20 in a similar way. And the last thing that I need to do with raw pointers, is I need to do two things with each pointer when I'm done with it. The first thing is I need to release the memory that I allocated for the thing the pointer points to, so that we don't keep holding onto that memory. So it's good practice to release memory when we're done with it. And with raw pointers we have to do that ourselves. The runtime system won't handle it for us. We have to do it. So if we don't release memory when we're done with it. And particularly if we didn't release the memory that score points to and then we allocated more memory for scored a point to that other piece that was allocated will actually stay in use by our program even though we're not using it anymore and we can't even get to it anymore. That's actually called a memory leak. And that's one of the big dangers of raw pointers. The other thing that we need to make sure we do after we've de allocated or deleted that memory or free to that memory or released that memory is we want to set score equal to null pointer because we could by mistake later in our code, try to access the memory that score points to. But if we've already released that memory, then who knows what's at that memory dress now. It could be garbage. It could be something else that was allocated in some other part of our program. And that would be a horrible thing as well. And that's called a dangling pointer, when a pointer points to something that has been released and it shouldn't try to access that memory anymore. So we want to do these two things every time we're done with the raw pointer, let's actually run this code and see what it looks like. So as you can see at the top we have a bunch of addresses. And so the address of the score pointer is this hex address. And then the address of the integer that the score actually points to is the second line. Here's the address of the D6 pointer and here's the address of that D6 die object. Here's the address of the D20 pointer and here's the address of the D20 die object. As you can see from the next line. The current score value is this big negative number, when we allocated memory for the integer. The runtime system went off and found a piece of memory for us that will hold an integer and we have whatever garbage happened to be in that piece of memory as the value of the integer, you saw in my code that I then D referenced. The score pointer and set score equal to 100. So that next line shows that we've changed the pointed to value the integer that we point to 100. The next two lines of code show that we created a D6 properly. So I'm D referencing the pointer and calling functions whether I'm using the D reference operator and then the dot notation or the arrow operator to do that. So the D6 has six sides on the top side is one. Remember that was our default for our die and then finally the D20 has 20 sides and the top side for the D20 is one. And that's a whirlwind tour of raw pointers in C plus plus, to recap In this lecture, we learned how to use C Plus Plus raw pointers, even though we should use C Plus Plus smart pointers as much as we possibly can. And we also learned that using C Plus Plus, raw pointers can lead to some really bad bugs, including memory leaks and dangling pointers.