SINGLETONS in C++

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey what's up guys my name is Bettina welcome back to my C++ series so it's been a really long time since I lost a bus bus episode but that does not mean this series is over haha Oh nor we in fact just getting started there's just so much in C++ to cover and in fact it's now 2020 which means tables cost 20 is on the horizon and of course I'm gonna have a bunch of videos on that coming in the future today though we're gonna be talking about something that is less a language feature of sabors plus and more of just a design pattern and that is a singleton what is a singleton why do I care why do I want to use it when do I want to use it all that stuff that's gonna be in today's video but first I want to thank our sponsor for this video hosting up now everyone needs web hosting of some sort whether you're an artist a programmer anyone who just wants a website on the Internet or some kind of server technology to run code that they've written you're gonna need some sort of web hosting and my favorite company for that by far is hosting it and let me tell you why first of all I absolutely love their control panel so many web hosting companies have these dream Lea complicated outdated web 2.0 looking like Chiyu eyes and all of that to set up your website which is just ridiculous if you just want to install a quick WordPress site which I think that honestly a lot of people should just do and that'll be that'll be fine for them it's as simple as just going to their beautifully designed control panel and just setting that up in just a couple of clicks and in fact they have built-in Diagnostics to help you in case something goes wrong hosting are by far the simplest in that regard they're also extremely well Christ and by extremely well priced I mean they're offering you ninety one up to ninety one percent off that's like I mean what even is that if you sign up using the link in the description below with my code ninety one percent off web hosting really I mean to be honest they're just they're just one of my favorite sponsors to work with because it's just such a good product and it's sore sore sore affordable go ahead and sign up using that link in the description to get up to 91 percent off all of their products make 2020 the year that you find get that website up and running because because it's time and of course a huge thank you to hosting it for being a wonderful sponsor and sponsoring this video so Singleton's what is the deal with Singleton's just left the monitor like in the frame like what's going on sure has been a while with these hippos Plus videos okay so I'm gonna keep this real simple as I'd like to do a singleton is basically a single instance of a class that you just have around and that's it so it's a class way you only intend to have a single instance of that class or struct because classes and structs have like pretty much the same thing in C++ now object-oriented programming in general the whole benefit of having these objects these classes is the fact that you can instantiate them multiple times it's not just all about being like okay I'm gonna write all of my code and then I'm just gonna instantiate this object and it's that's it like that I'm not gonna instantiate more than one instance of this object a little bit we're a little bit counterproductive why do I even need an object in the first place and that's the thing if you are using a singleton it's quite easy to just look at it and be like well this does not need to be a class because if you only have a single instance of an object then what you really have is just one singular set of data and then probably some functionality to go along with it so in other words we have our class members which represent our data and then we have the other thing which is all of the functions that represent you know operations usually performed on that specific set of data or otherwise to interact with that data those are kind of the two blobs we end up with and if that is the case if we don't intend to instantiate multiple instances of a particular class and thus you know we would want it's their own kind of version of the data upon which those operations will kind of be performed on not to complicate things but if we don't need that then why do why would we even use a class now Java and c-sharp they're inherently object oriented languages that they kind of force that upon you specifically Java I'm what I'm just gonna just pick on Java for in Java everything has to be a class you can't have card outside of a class which means that if you want this kind of static will say functionality where you don't actually need instantiation then you have to just make static members in your class and a static static group of functions now we in C++ are not really bound by those rules because we don't have to write a class we can just have functions that are you know part of some kind of namespace or even in the global namespace that do not belong to any kind of class and furthermore we can do the same thing with variables we can have completely global variables or we can have static variables that are tied to a particular translation unit or in other words a particular CPP file C++ incredibly flexible language lets us do whatever we want but the singleton design pattern where does that come into play Singleton's super useful for when we essentially want to have functionality that applies to some kind of global set of data that we just want to potentially repeatedly reuse so a few really basic examples of Singleton's a random number generator class we just want to be able to query it and be like give us a random number we don't want to have to instantiate it go through all of that stuff nor because we potentially want to instantiate it once so that it actually seeds that random number generator and sets up any other kind of axillary things I guess that it actually needs but then we want to just call some kind of function that will give us a random number based on what we've initialized it with simple as that another good example is something like a renderer a renderer very commonly is a very global thing we typically don't have multiple instances of a renderer we have a renderer to which we submit all of these rendering commands and then it just kind of well it renders things for us if we break this down into like OpenGL we're literally calling OpenGL calls through our renderer potentially that all in itself is a global set of functions that's not something that relate to some kind of object at all they're just C style functions no classes nothing to do with that at all so what we want potentially is just to be able to almost use the class as a namespace to just call certain function and that's where this whole singleton thing gets a little bit messy and why I really want to dive into some code and take a look it's because ultimately speaking Singleton's can just behave like namespaces singleton classes can just behave like namespaces there's nothing to actually tie them to that word class I'm gonna say this once very clearly Singleton's in C++ are just a way to organize a bunch of global variables and Static functions that sometimes may or may not act upon those variables into one kind of organized blob that is essentially under a single namespace that is what that is what a singleton is now of course it can be flexible around those rules but that's basically it let's just dive in and take a look at some examples how we can write a singleton and some other things along the way so let's start out with a really really basic example of a singleton we'll just write a class we'll call it singleton and then I'll kind of explain everything that makes this singleton a singleton so to start off with we don't want to have a constructor because if we have a constructor that is just public then it's going to allow people to be instantiated so what you would typically do is just mark this constructor as private meaning that this class can't be instantiated outside of within this class the next step is to provide a way to actually access this class statically so we would need some kind of static function which returns either a reference or a pointer of this particular type and you typically call it something like get instance or just get for short and then what this needs to do is return some kind of instance of singleton now because it is a singleton there is obviously just one instance of this class for your entire application so the way that you designed this is completely up to you I'll show you a few ways a more traditional way is just to simply make a static instance of that singleton class somewhere here inside your private members so in other words I would just make a static singleton called something like s underscore instance however because it is static it needs to actually be defined somewhere so in some kind of CPP file I would now need to take this singleton and actually define it like so like any kind of static member and then once I've done that inside my get function I can simply return this s instance this is kind of a very popular singleton pattern this is probably something you do especially in a language such as Java you wouldn't exactly need this definition but you would set it up this way and what this means is that if I have a main function over here I can simply access that singleton by just calling singleton get just like that and then from within there if I had some kind of function like a void function or something like that then I can simply just call the function on that singleton instance and there we go I can statically access this singleton as if there was just one instance of it because I can just use this get function now semantically this does have a few flaws for example I can just take this singleton get function and assign it into a completely separate singleton instance so I can do something like this what I probably meant to write in this case is a singleton reference like this because I can absolutely do this and then use this instance over here like so however if I accidentally forget to do this what will actually happen is all of this data inside the singleton will be copied so in fact I've created an additional singleton instance and if I actually had data here like I had some kind of member here then of course that data would be copied into this new object and that of course is not what a singleton is it defeats the entire purpose of a singleton I just want one instance so to combat this what you would typically do is simply delete the copy constructor because if I come up here and I just mark the copy constructor as delete like this right then it won't let me do this I have to actually write this as a reference or something like that using Auto is also a completely valid thing to do but again remember that you need to explicitly write reference here and then you can use it like so ok cool so this is a completely arbitrary example hopefully it makes sense let's deal with something a little bit more real what I'm gonna do is instead of this being a singleton class which means nothing I'm gonna try and make a random number generator class so I'll just copy and paste all of this stuff and then I'll just apply this over here and let's just say that I want to write a function that generates a random float so I'll call this float float now this is not a video about random number generation so what we'll do is we'll kind of just have our random generator flirt here we'll just set it to 0.5 and that is what this function will return but pretend that of course it would it's a real function that randomly generates a number and then returns it through this design if I want to actually generate a random number all I have to do is call random yet and then float it and I'll get a random float presumably and I can assign this like so float number equals random get float now this is totally legit and it's a great use case of Singleton's because you don't need to have multiple instances of a random number generator potentially I mean of course you could justify that but for this case let's just say we have a very simple random number generator it gets seeded in the beginning potentially and then just reuse throughout our program simple as that we don't need anything complex let's kind of break this down and take a look at what it actually consists of so we have a deleted copy constructor we have this get function and then we have our actual kind of meet this is the actual function that returns a class member now this is one of the things that make the singleton as singleton the fact that this is an actual class and it can have class members such as this random generator if this just returned some kind of static value like this then of course it could simply be marked as static and we wouldn't in fact need a singleton at all but the thing that makes a singleton a singleton is the fact that it is in fact a class so it can support all of these class features such as class members you could definitely look at this and see it as being annoying because instead of just calling random floor which might be desirable I have to call random get and then floor it which of course just adds some more complexity I could kind of fix this by just bringing this out and being like order random equals random get and then from there calling random float and this might be something I do if I have this whole kind of function scope where I'm just gonna be using this random number generator however of course that is an extra line of code and it is a little bit annoying so how do we get it to this state and then obviously still keep it as a singleton with class members well what I like to do is simply make another function so I have my kind of implementation of what float is it returns a random generator what I'll do is I'll move this actual function into the private section here and I'll rename it so I'll call it something like float internal or float some people call it float in pool for implementation I like to just stick an eye out the front now this does kind of make it look like an interface potentially if you're using that convention but I like using it for these functions because I'm basically saying that this is the internal float function and then what I'll do our here is write a static float function so this will be static float float and then what this will do is simply return yet dot I float so I have this kind of indirection here obviously once all of this gets in lined by the compiler you really shouldn't see any kind of performance hit or anything from all these function calls because in the end we're just kind of retrieving the value zero point five and that's it but what that means for us is that we can in fact run this code here and if I just print this out to the console you can see that I do get my value zero point five and everything is fine and I haven't had to call get at all so that's just like a little hack that I like to use another route you could go is simply just not even worrying about this indirection because all we're trying to do here is return a value you can just return get dot M underscore random generated that way you don't need this internal function at all but of course in a lot of cases you probably want to keep this internal functionality and the benefit here obviously is that since it is not a static function it has access to all of the class members without having to like retrieve you know the actual instance or anything like that so that's another benefit now the last thing that I want to show is this kind of get function here because the way that we've written it right now means that we actually need a static instance over here in the class members and then we need to define it in some kind of translation unit that's a little bit cumbersome I don't like to do it that way a better way to do this is to actually move this static declaration inside this static function so what I can do is get rid of this entirely as well as this and then simply in this get function I can write static random-ass underscore instance and in fact like I can just call it instance if I wanted to that's totally fine as well so what this is doing is actually having a static variable inside a function which means that this still is in fact in static memory once they get function gets called for the first time it will be instantiated and then on subsequent times it's just in static memory so it'll just be reference it's basically the same as what we did before but you can see that it's a lot cleaner because I don't need to have anything here at all and functionally it's identical if I come down over here and I want to call random flirt which of course goes through that get function then obviously I'm going to get the exact same result so that's pretty much all there is to a singleton you probably want to do a few other things to clean it up and make it a little bit better for example you might want to delete the assignment operator as well but I've just kind of simplified this and made it a little bit easier to understand so to summarize the core of a singleton is this kind of functionality here where I have a single instance that I create once which in this case happens as soon as it's used for the first time and then the lifetime of this singleton would simply be the lifetime of your application and then once I have this singleton I can simply write any any amount of non-static methods and access them via this get function or if I want I can kind of remove one level of indirection and write these static functions which internally just map to member functions which can access member data and all of the functionality of classes now the last thing I want to show you guys is what happens if I just don't treat this as a class what's the point of even having a class in C++ why can't I just write a namespace I'll call it random class in this case that just has all this functionality and the answer is you can I can just write this and I can write a static float called s underscore random generator and you know set this equal to 0.5 and then have a function called float like this static flirt floor which then returns s random generator there's no functional difference between having these two and in fact if I just call random class flirt here you'll see that it's identical I mean I do have this extra variable which is just tied to a namespace instead of a class I do kind of lose his private public functionality but you can get around that if I had a header file which just simply contained a declaration for this function and then I had a C++ file which implemented the function and also had a static version of this then I've effectively hidden it from other files but again there's no real downside to using a class and of course it does let you keep it a little bit more organized not to mention that I do in fact lose the functionality of being able to assign the instance of this class to like a variable like I did before okay so hopefully that kind of gives you a little bit more of an example it's sometimes hard to just sit here and talk are you guys even though I have so much I want to say obviously a lot easier to actually dive in and take a look at the card itself hopefully you guys enjoy this video if you did please hit that like button don't forget that I do have a patreon as well patreon come for later the Cherno huge thank you to everyone who helps support this channel please let me know if you want to see more kind of design pattern videos like this singleton one if you have any thoughts about Singleton's leave them in the comment section below so that we can have a nice discussion let me know if you use them when you use them or use them for if you don't like using them and why all that stuff leave it in the comment section below huge thank you again to hosting it for sponsoring this video guys check that web hosting out up to ninety one percent off it's incredible I will see you next time goodbye [Music] you [Music]
Info
Channel: The Cherno
Views: 101,111
Rating: 4.9431896 out of 5
Keywords: thecherno, thechernoproject, cherno, c++, programming, gamedev, game development, learn c++, c++ tutorial, game engine, how to make a game engine, game engine series, singletons, singleton
Id: PPup1yeU45I
Channel Id: undefined
Length: 19min 15sec (1155 seconds)
Published: Fri Feb 07 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.