Jump to content
  • Advertisement
Sign in to follow this  
Cedric_

Singletons that creates multiple copies?

This topic is 4814 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi all, long time since I posted now, starting to miss you. Okay, so I've some days ago now discovered the secrets of singletons. Or well.. not really discovered but, at least I've found out about 'em. So I'm going to try out a mud-project, seeing how far I can take it, and I'd just want some help with these singletons. Btw, language is CPP. I've checked out both some singleton tuts on The Code Project as well as DevX. Perhaps I've missunderstood something, but isn't one of the things with singletons meant that it should NOT be possible to create several objects of a singletonclass? At least that's what I thought, that and making it possible somehow to have a global "access point" as they call it, in your application. Something that would really be handy now cause I'm trying to start small and get a nifty logclass up and going first of all. I searched Gamedev and found 'streamer' posting this concise class(opposite of how damn long my messages always becomes, sorry!).
class Singleton
{
public:
static Singleton * instance ();

protected:
Singleton ();

private:
static Singleton * m_pInstance;
};

Singleton::Singleton()
{
}

Singleton * Singleton :: m_pInstance = 0;

Singleton * Singleton :: instance ()
{
return ((m_pInstance ? m_pInstance : (m_pInstance = new Singleton)));
}

int main()
{
	Singleton *s1 = Singleton::instance();
}


So I'm trying to understand this. When I typ in "Singleton *s2 = Singleton::instance();". The compiler actually lets me create another instance of the Singletonclass. Why? It shouldn't, right? AND, do YOU know any technique that doesn't force me to declare m_pInstance outside the class? If you know any other help to as to exactly why with the help of singletons, I actually can get a global "accesspoin", please tell! As I said, language is CPP. Thanks in advance, I know there usually are a lot of helpful people out there!

Share this post


Link to post
Share on other sites
Advertisement
Quote:
Original post by Cedric_
So I'm trying to understand this. When I typ in "Singleton *s2 = Singleton::instance();". The compiler actually lets me create another instance of the Singletonclass.


It doesn't. The pointer will be the same as the first time. Only when m_pInstance is 0 does a new object get created, at which point m_pInstance is made to point to it.

Quote:
Why? It shouldn't, right? AND, do YOU know any technique that doesn't force me to declare m_pInstance outside the class?


You don't have to declare it outside of the class, but you sure do have to define it in exactly one translation unit. There are no ways around that fact.

Quote:
If you know any other help to as to exactly why with the help of singletons, I actually can get a global "accesspoin", please tell!


If it is a global access point you need, you might as well just use a global. Singletons do not really offer you any extra "protection" that makes them any "better".

Share this post


Link to post
Share on other sites
The key bit I think you are missing is that this piece of code

return ((m_pInstance ? m_pInstance : (m_pInstance = new Singleton)));

it only creates a new instance if one doesn't exist already.

Share this post


Link to post
Share on other sites
Quote:
Original post by Cedric_
It shouldn't, right? AND, do YOU know any technique that doesn't force me to declare m_pInstance outside the class


its called java

Share this post


Link to post
Share on other sites
Quote:
Original post by Fruny
If it is a global access point you need, you might as well just use a global. Singletons do not really offer you any extra "protection" that makes them any "better".


I'm not a real big fan of singletons myself, but they do offer some protection from global construction order problems when dealing with multiple inter-related globals that are defined in separate modules.

[EDIT] Sorry for my wording there, you might have to read it a couple of times to get what I mean [wink]

Share this post


Link to post
Share on other sites
I don't think that you are creating another instance of the singleton, rather the instance function is checking if the private pointer to the singleton is populated, if so it just returns a copy of the current singleton instance. If it isn't already instansiated it calls new() and then returns a copy of the pointer.

The more generic way of using this would be directly through the instance() function:

Singleton::Instance()->funcName();

The 1st time the Inshtance() function is called it instansiates a private pointer to be used on subsequent calls to Instance()...the next time It doesn't have to instansiate the pointer, so it doesn't.

If you are using a singleton design you might also need to be aware of functions calling it AFTER you have deleted it. For example a logging class might be a singleton and might be called by some deep lying function in another class (after you've manually deleted it).

This being the case you probably want to write your own delete function (I don't mean a function that overloads the global delete - call it remove() or something) and use the atexit() function, which gets called when a program exits.

Hope that helps a little.

Share this post


Link to post
Share on other sites
Quote:
Original post by Thunder_Hawk
I'm not a real big fan of singletons myself, but they do offer some protection from global construction order problems when dealing with multiple inter-related globals that are defined in separate modules.


Yes, you are right. I've mentioned that here an hour ago. [grin]

How about a Schwarz counter? That's how the standard stream objects are initialized.

Share this post


Link to post
Share on other sites
Thanks guys for the reply! And yeah, you're right Fruny, I could probably just use a global, but at the same time I want to learn about singletons. Cause as I said in my first post, I just found out about the technique.
Edit: Btw, global isn't really proper OOP right? Or how was it?

And yeah, I see now what I was missing. They're pointing at the same object, of course.. Thanks for the clarification! Stupid of me.

"You don't have to declare it outside of the class, but you sure do have to define it in exactly one translation unit.":
I don't think I understood that perfectly. Could you make an example please? I guessed you meant declaring the value in one line like "static Singleton * m_pInstance = 0;", but apparently that doesn't work.

"The key bit I think you are missing is that this piece of code"
Yes you're right. I've actually never used the '?' myself, so I haven't fully understood it. Better check it out right away, thanks!

Thunder_hawk: "you might have to read it a couple of times to get what I mean" You're right about that! Thanks for the info! :D

garyfletcher: Thanks for the clarification!
"Singleton::Instance()->funcName();" I'll check out that technique see what I can make out of it! :)

yeah, the atexit(); function proposal was nice!


"How about a Schwarz counter?"
Hmmm, can't say I've ever heard of it before. I'll check it out, thanks!


Many thanks guys, it's appreciated! Really appreciated. I hardly finished my post and you already replied more than enough!

[Edited by - Cedric_ on September 12, 2005 3:52:02 PM]

Share this post


Link to post
Share on other sites
Quote:
Original post by Cedric_
Thanks guys for the reply! And yeah, you're right Fruny, I could probably just use a global, but at the same time I want to learn about singletons. Cause as I said in my first post, I just found out about the technique.


Just keep in mind that a lot of people abuse singletons. Just because you only have one of something isn't enough to justify using a singleton.

Quote:
"You don't have to declare it outside of the class, but you sure do have to define it in exactly one translation unit.":
I don't think I understood that perfectly. Could you make an example please? I guessed you meant declaring the value in one line like "static Singleton * m_pInstance = 0;", but apparently that doesn't work.


In C++, there are two ways to make the compiler aware of a symbol (function, variable...). Declarations just inform the compiler that the symbol exists, somewhere else in the program, without actually bringing that symbol into existence. That's what happens when you give a function prototype, for example. You told the compiler the symbol existed, and what it was, so it'll let you use it. Definitions are the bit of code that actually creates the symbol. That's when you create a variable, give the body of a function, the contents of a class... Now, C++ source files are all compiled separately. While it is processing foo.cpp, the compiler is blissfully ignorant of the existence (and contents) of bar.cpp. The only thing it sees is foo.cpp and all the files that it includes, which the preprocessor literally merges into one single input file: the translation unit. Once all the translation units have been compiled, control is passed to the linker which will join them into a single executable. It is at that point that symbols that have been declared in some translation units are joined with their definition. For any given symbol, over the whole set of translation units that make up your program, every symbol should be defined once and only once, that's the "One Definition Rule".

How does that relate to your problem? Well, in the Singleton class definition, static Singleton * m_pInstance; is only a declaration. You told the compiler that, come link time, the variable would exist somewhere in your program, but you haven't created that variable yet! You need to do so. You can't put the definition in a header file, otherwise every translation unit that contain that header will define the variable, and the linker will not be happy. So, in the end, you need to put the definition into a single CPP file, so that it belongs to a single translation unit.

Share this post


Link to post
Share on other sites
Thanks for taking your time Fruny.

"Just keep in mind that a lot of people abuse singletons. Just because you only have one of something isn't enough to justify using a singleton."
I will try to remember that one, and at the same time I'm sure I'll probably make that mistake at least once. Though really the thing I was most interested in was just the global acces point. I saw how nifty it looked at a friends application, he just needed to include the header-file in each .cpp-file and got access to the object.


"How does that relate to your problem? .."
Wow, talk about a detailed explanation! :)
I read it carefully trying to pick up everything, that sure was great to have been told even though I was a bit aware of some of it in the back of my mind.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!