 Hey everybody, it's Brian and we're going to continue our conversation about automatic memory management using Qt, or I should just abbreviate that to Qt memory management. This video is going to cover two specific classes, the Qscope pointer and the Qshared pointer. What are these? Well, these are called smart pointers. If you don't know what a smart pointer is, remember in C++ when you use the new keyword, you create an instance of an object out on the heap, you now own that lifecycle. And yes, Q objects do have the parent-child relationship, which automates that very cleanly, but sometimes you need a little extra, well, muscle power, you got to be able to do things. And that's where smart pointers come in. Now, things have changed over time. You may be, especially if you know C++ asking, why are you messing around with this? Why aren't you using the standard library or Boost or any of the other things out there? Well, this article written in 2009 summarizes that beautifully. This was written in 2009, but it still stands the test of time. Most of this is still fairly accurate. How many smart pointers does Qt have? Well, in this article eight, and the updated documentation shows actually more, and I actually expect that to keep growing. The reason why we need smart pointers is we as mere mortals lose track of a pointer, and that's how problems are born. And it gets very complex. You see each one of these has their own special use case. For example, scope pointer, one of the things we're going to cover, the pointer will automatically delete when it goes out of scope, much as if it was a normal variable living out on the stack. Shared pointer is different. Shared pointer holds a strong reference to a shared pointer, meaning you're going to just share this all over your application, and you can feel free to dive into the documentation. But basically what we're talking about here is reference counting. Basically it's keeping track of how many things are looking at it, and when it's no longer used it will automatically delete it. This gets very complex under the hood, but at its core really each one of these has its own special use case. I'm not going to dive into all of them just yet, but I want you to be aware that they exist. This article really summarizes very nicely why each one exists and what it's used for. So feel free to go out there and read it. At the very end of this article though, it does address why not the standard library, boost and other technologies. There's reason for that. They don't really do it the cute way. Now I'm not saying cute's better. I am saying that a lot of the things in cute were put into cute because they simply didn't exist anywhere else at the time. Now over time they will more than likely be slowly phased out in favor of the standard library, but right now you have both. So I'm not saying choose cute over standard. I'm just saying you have these in your arsenal that you can use. All right, let's dive in and let's take a look. So let's go ahead and test Q scope pointer. So I'm going to go in here and we're just going to add the include to it. And then we're going to make a very, very simple test function. What we're going to do now is we're going to say Q scope pointer. And this is a template. So we need to, of course, work with it. And we want to use the test class. Let's call this PTR. And we need to initialize it. You notice we're going to initialize it with a pointer. So I'm going to say new. Now in the real world, likely you would call another function, which would generate this for us. And then you would just grit that pointer and then shove it right into here. All right, that being said, now we have a wrap this pointer with a Q scope pointer called PTR. We can go ahead and do something with that. Now before we actually do anything, let's modify our test class ever so slightly. So right now it does absolutely nothing. It's just got a constructor and a deconstructor. I'm going to go ahead and say void message. And we're going to make a Q string in case you've never heard of Q string before. It is a, well, it's actually pretty amazing. We're going to cover it in depth in another video. But if you highlight it and hit F1 on the keyboard, the Q string class provides a Unicode character string. That's right, Unicode, baked right into Qt. You really don't have to do anything. It's just baked right into Qt and you have a massive amount of string processing you can do. And it's all Unicode. It's not ASCII. This is amazing. All right. So in our message, we're going to right click Refractor, define in our implementation file. And then we're simply going to grab this and let's go ahead and just print out the value. Now back in our main file, I'm just going to say PTR dot. And we have two things here. We can either worked with the Qscope pointer or we can work with, you guessed it, the class that we're using. In this case test. So I'm going to say PTR message and it just calls it directly. This is great. I love this. So now you can just work with it as if it were the pointer itself. But it's wrapped in this beautiful Qscope pointer. Let's go ahead and test this out. Now remember, you typically get this pointer from another function. I'm just wrapping it all into one little function for demonstration purposes. And sure enough, we see that full object lifecycle. The test is constructed. We can work with it directly. And then it's automatically deconstructed when it goes out of scope. So just a quick review. It went out of scope right here. And it's automatically deleted. Next we're going to take a look at Qshared pointer. Remember, this is designed for the pointer to be shared, hence the name Qshared pointer. Really, what we're going to do is we're going to create some monstrosity like this. And for newbies, this may look intimidating, but this is actually a fairly simple app. We've got our main function, we're going to create a test shared. So we're going to create a pointer in main, pass it to test shared. Then we're going to, of course, pass it to another function called step. Step is going to call a function called work multiple times. And then ultimately finish is going to get called. The problem here is that pointer should automatically delete itself, but not until we're finished. This is the beautiful part about Qshared pointer is it keeps track of where it's all referenced and what's going on. And you can make it infinitely more complex than this. You can spread it across multiple classes and whatever you want to do. I'm just really dumbing down this example so newbies can wrap their head around this whole process here. So let's take a look. I'm going to make our function called test shared. And we are going to get a raw pointer call this test from our main function. And now we want to do something with that. So let's go ahead and say, test shared new test. So we're just getting that raw pointer right from our main function. We're here. We're going to here. And in here, what we need to do now is actually wrap that pointer and take ownership of it. So I'm going to say Qshared pointer. This is templated. So you have to tell it what it's working with here. Let's call this, let's give it a startling name like PTR short for pointer. I know. I'm really horrible at picking names. You ever have one of those moments we just stare off in space for like five minutes trying to pick up variable name. So I'm going to say PTR dot. And then we can just work with this directly. I'm going to say message. So we're going to send out some sort of message. And in this case, I'm just going to say starting in case I've lost you, this message function is actually part of the test class. You can see it right here. So we're actually just working with that pointer directly, even though we just wrapped it with a Qshared pointer and we're now tracking that reference from here. We're going to make another function flipping back to our diagram. We're going to go into a function called step. So let's go ahead and say void step. And this is the confusing bit for newbies, you're not going to ask the pointer. You can certainly do that, but then rewrap it and it just becomes a nightmare. Instead, what I like to do is simply this Qshared pointer. That way me as the developer looking at this function, whether this function is in a completely different file or different class, I know right away, we're doing automatic memory management and I don't have to worry about this pointer. Rather than if I was just looking at this, I may suddenly freak out and then try to reimplement it or possibly even wrap it in a different one, like a Qscope pointer, which would delete it automatically. You don't want to do that. Okay, so what step is going to do is, well, something like this. I'm going to say, and it's going to start working through that whole workflow that we got going on here and back at our diagram. Our workflow is just going to be calling the same function multiple times. But in the real world, it would be multiple steps of something completely different. So let's go ahead and implement that function. And then let's go ahead and loop. So I'm going to say, four, int i equals zero, i is less than three, go in increment. And now we can just simply send that over. Makes it ridiculously simple. And notice we can copy it. We're not passing a pointer or an address of, we can just copy it. Yes, it would be faster and more streamlined to do an address of and just pass the whole thing around. But then again, I'm trying to do things, well, the slow way just to show you that it all just magically works. All right, flipping back to our diagram. The last step in this process would be to call this finish function. And finish, of course, has the major responsibility of saying we are done and we want to kill this whole pointer thing. Now, everyone is probably just like Roth with fear going, uh-oh, what do I do? This is going to be some special, special call or some special thing. Well, you really don't have to. So I'm going to say finish. And that's it because it's doing the reference tracking for us. We don't have to worry about it. It'll all just magically work. So let's track down here. We're going to get rid of this scoped just so we don't have clutter on the screen and we're going to test our shared. So this is going to call test share with a pointer going here. And now we need to actually go into our step to make that whole diagram work from step. It's going to go in here and go to work. But of course, once we're done stepping through, we should call finish. Now we have our complete workflow. Finish is going to go in here and cute under the hood is going to track all that force. And everything should just come together in a beautiful little dance and it should know when it's no longer needed. And you can see we have started, we have stepped, we are doing three works. We finished and cute realizes. Hey, it's not being used anymore. Go ahead and wipe it out. That is extremely, extremely nice. I love working with that. Now, if you want to deep dive through the documentation, you can, of course, reset that. But you would be at risk of causing a memory leak. So when in doubt, I almost always let the automatic pointer classes take care of the pointer for me. I hope you enjoyed this video. You can find the source code out on github.com. If you need additional help, myself and thousands of other developers are hanging out in the Voidrealms Facebook group. This is a large group with lots of developers and we talk about everything technology related not just the technology that you just watched. And if you want official training, I do develop courses out on udemy.com. This is official classroom style training. If you go out there and the course you're looking for is just simply not there. Drop me a note. I'm either working on it or I will actually develop it. I will put a link down below for all three of those. And as always, help me help you smash that like and subscribe button. The more popular these videos become, the more I'll create and publish out on YouTube. Thank you for watching.