Right now, you understand both how a class exist in C++, as well as how variables are created and stored. I want to take a minute and talk about the intersection of these two topics, where an instance of a variable, any variable, including objects like our cube class, can be stored three different ways. They can be stored directly in memory, accessed via a pointer, or accessed by a reference. Let's look into detail about each of these and how they interact with their class. As we learned, by default, all of the variables are directly stored in memory. When we have direct storage in memory, the type of the variable has absolutely no modifier, and the object size in memory is exactly the size it takes up to store. For example, we saw many cubes, these cubes we talked about being stored in stack memory. We've talked about many integers. We've talked about crazy different classes, like an HSLAPixel. We've talked about specialized classes, like an HSLAPixel you see in the assignments. You've also seen us storing things by pointer. We introduced the idea of a pointer when we started talking about heap in memory, and the type of a pointer is the type of the object modified with the asterisk. A pointer takes on the memory value of another piece of data. The exact length of that memory address is going to be the memory address width of the system. So, for example, I'm on a 64-bit machine. On a 64-bit machine, the memory address is 64 bit long. As we learned with heap memory, a pointer simply point to the memory allocated for the object. We see here is a cube pointer denoted by the star. Here's an integer pointer denoted by the star. Here's the HSLAPixel, again denoted by the star. The star denotes these are each pointers. There's a third way of storing that we've made it references tuple we haven't formally defined. That is storage by reference. A reference variable is a special type of variable which aliases existing memory by name, and is denoted with an ampersand. So, a reference variable never stores any memory itself. A reference variable has no size. It takes zero bytes of memory to create a reference variable. A reference variable simply refers to some existing memory. When you create a reference variable, we have to alias that reference variable at the moment we create it. For example, if we have a cube c that we're creating as a reference variable, it must be alias to the cube, an existing variable, as soon as it's created. Int ampersand i is a reference variable i that's aliasing count, and again it's taking on this alias as soon as it's being created. Because we're aliasing the memory address, when we change i or change count, we're changing the exact same thing. This is simply an alias to memory that's already created. It gives us a second way of referring to it. Because reference variables have to be assigned when they're initialized, we can see that a line of code HSLAPixel reference variable p semicolon is not a valid line of code, because that does not create an alias when it's initialized, and you'll see that if you run this code through a compiler, this code won't even compile. So, let's look at why this matters in a real example. So, suppose we're going to take our cubed class, and we're going to make our cube class currency. Our cubes have a value to them based on their volume. So, a tiny little unit cube has only a volume of one, and its value is just one. So, a little larger cube, a cube that has a side length of five, has a value of this volume of the cube. So, five cubed is 125. So, a cube of length five is worth 125 currency. Likewise, a large cube of length 10 is worth 1,000 currency. So, every time we create a cube, we're actually creating currency. So, we're now playing the role of a banker. Whenever we will receive money, we want to actually make sure that we get the cube itself. We don't want to create a copy of this cube. We don't want to do anything else, except for transfer the cube to someone else. If we're creating a copy of a cube, we're creating inflation. We're being a bad banker. We want to make sure to understand exactly what's happening to this cube in memory. So, what I've done is I've modified the cube class so that we have some output that gives us context on what the cube is doing. So, here's three different functions of the cube class. The first function that I have here on lines 12 through 15 is a custom one parameter constructor. So, notice the class name is cube, the same as the class itself. It has one parameter. We see it has no return value. So, it has to be a constructor. This is a one parameter constructor, and it's going to say we created some amount of money. So, whenever we call the constructor, we're creating money. The second type of constructor, the copy constructor we have here, takes in a cube by reference. So, notice that this reference that we've thrown around before shows up, and this means we're not going to create a new cube when we pass this argument in. We're going to simply have the cube alias to us. Then, this alias cube is going to copy into this newly constructed cube. So, we see on line 19, we're going to say Created, get the dollar amount via copy. So, whenever we create new money via copy constructor, we'll see the via copy. So, both of these constructors create new money. So, we want to be very careful when new money is created. The third function is the assignment operator. The assignment operator transforms an instance from one value to another value. So, this again has the potential to create money. So, we're going to say transformed, and we're going to talk about the current volume that the cube has beforehand and the volume it has after. So, it's going to transform its old volume into the new volume. So, it's actually changing the value of a cube. It's growing or shrinking the cube. So, all three of these things are concerning, because all three of these are creating money. So, we want to be really, really careful about when these things get invoked in our code. Here we're talking about money. But in computer science, whenever an object is being created, it's taking up memory. There are resources really being allocated when all of these operations are performed. So, we're seeing a real example with money, but this is actually a real concern in all programs because resource is on a computer, we want to be conservative about. So, our very first example, we're going to look at what happens when we transfer a cube to another cube by value. So, here, on line 13, we create a cube of width 10. So, we're creating a cube that's worth $1,000. On line 16, we're assigning that cube to my cube. So, because this is being initialized right here and it's being initialized with an initial value, we expect for a copy constructor to be called. Here we're transferring the cube to another person. What's actually happening at the end of this program is we don't just have one cube, we have two cubes, because we construct your first cube and then we used a copy constructor to create your second cube. So, I expect that this program is going to create $2,000, which is not what we want to do. But let's go ahead and find out what happens when we run example one by value. Going into the CPP memory trajectory, going to example one, running make, running dot slash by value. By value, we created $1,000 and created another $1,000 via copy. Here we created $2,000, certainly something we didn't want to do when we just wanted to transfer $1,000 another person. So, we created some extra memory here. So let's see if maybe using a different memory technique will help us out. The second piece of code we're going to look at is looking at this byReference. So on line 13, we create a cube using the constructor. So, we have a cube of $1,000. On line 16, we transfer the money to another person by aliasing the money because we have a reference variable here. So, myCube becomes an alias of C. So, what happens here is myCube is going to be this cube as well as C is also going to be this cube. So because we're simply creating an alias of existing memory and not creating any new memory, we expect for the cube to construct exactly once and nothing else to happen when we run the byReference program. Let's see if that happens. I've already compiled this code, so I can just go ahead and run in dot slash, byReference, and byReference creates a single cube worth $1,000. Awesome. So this gets to what we want. We only created a single cube, now we have two different instance of this variable. Though in doing that we haven't really transferred anything, we've just aliased to people to owning the same cube. So let's see other techniques and see what else we can do. So, this third program in example one is going to create the same cube we've had before. So, we're going to create a cube of $1,000, and then we're going to transfer this cube via a pointer. So, myCube is going to be a new stack variable that is a pointer. So, here we have a new variable called myCube, it's a pointer, and it points to the memory that C is defined in. So, instead of having an alias where we have two variables that are directly the exact same cube, here we have two variables, one is the cube and one is a pointer to the cube. So, just like the byReference, we expect byPointer to only create one cube that is $1,000, let's see if that holds true. Running dot slash byPointer, we see that it creates exactly $1,000. Awesome. It's we expect. Let's try to get something a little more complicated and something more akin to actually transferring money rather than just changing variables around. So, up until now we've just done everything inside the main function, but what we really care about is actually passing money around so that we can have a function like transfer money, that we can give money to somebody else. Similar to three different ways of storing access to variables, we have three different ways that we can pass variables around two functions. We can pass them by value, which is the fault way, we can pass them by pointer by creating a pointer that we pass along, or pass by reference, which again is modified by the ampersand, and acts as an alias, it doesn't make it copy, it just makes two different variables alias the exact same memory. So, looking at our first function, we're going to again look at by value, by reference and by pointer. Looking at by value in example two, we're going to create our cube again, of $1,000, and now we're going to send the cube off to transfer the money to somebody else. Here we're sending the cube by value. So, the cube is going into this function by value, and we expect because it's being passed by value, that it needs to be copied from the main function to the send the cube function. So, we're going to expect here that it's going to create $1,000 and then create another $1,000 via copy. So we expect to see a $1,000 being created and then a second $1,000 being created via copy, when you were in example two by value. Let's see what happens. Moving into example two, running make to compile, and now running dot-slash byValue, we see it creates $1,000 and then creates another $1,000 via copy. This copy is called the sendCube function, which sends a cube money somewhere else. Unfortunately, this way actually makes a copy so you're really sending somebody a copy of your check and not the currency itself. Let's see if we can do better. Here we see a second example where we have a main function, creates a cube worth $1,000, and this cube worth $1,000, we are sending using the exact same code as we used in the by value. The only difference we see here, sendCube looks the same, when we look at a definition of sendCube, it has an ampersand, we're sending this variable by reference. By setting this variable by reference, we aren't copying this variable anywhere, we're just sending an alias of this variable because no copies are made, we expect a cube to only ever have been constructed once and only $1,000 should ever be created. Let's find out what happens when we run byRef. Running dot-slash byRef, we see it creates only $1,000 exactly once, awesome. Now let's look at by pointer. Finally, the very last piece of code is going to look a little different than the previous piece of code. We still create a cube worth $1,000 in memory. Ow we sendCube, and notice that we're sending ampersand of C. Remember, the ampersand operator before variable gets the memory address of C. So, we're setting the memory address of C into sendCube. Because cube is a pointer, we need a memory address. So, we're sending the memory address to get to that cube, and C inside of this function actually points to this cube. So just like what you saw in main, we can manipulate memory as we're sending it through functions by value, by reference or by pointer, and just for completion let's go ahead and run this code and let's see that it only creates $1,000 exactly once and then the pointer points to this object without actually creating a second version of it. Running dot-slash byPointer. Exactly what we expected, it creates $1,000 and it does that exactly once. The final thing to mention is that we can return by all of these different types. We can return by value, we can return by pointer, we can return by reference. When return by value we're making a copy. When we return by pointer, we're going to return a memory address associated with that variable. When we return by reference, we're returning an alias to that variable. As we mentioned when we first talked about this, you should never return a reference to a variable that's created on the stack, that's just going to cause problems for you, the compiler hopefully is going to give you a warning, but you'll want to get out of the practice of ever returning by reference when you're returning an internal stack variable. We'll see more about this once we get into data structures. The big idea takeaway is we have three different ways of storing variables. We can store them directly, we can store them by pointer or we can alias to some other existing memory. So, that is by value, by pointer and by reference. These three different ways of storing data allows us to be really flexible and have a lot of control over exactly how our memory is getting copied around. This cube class provides a great framework for you go play around with the code and really see how the cubes gets called when it transforms money, when it creates money, when it creates money via copy constructor, and all of different things you can do with the cube class. So, I hope you take a look at it and we'll go back to talking about more properties of a class in the next video. I'll see you then.