tags:

views:

968

answers:

8

I'd use a singleton like this:

Singleton* single = Singleton::instance();
single->do_it();

I'd use an unnamed class like this:

single.do_it();

I feel as if the Singleton pattern has no advantage over the unnamed class other than having readable error messages. Using singletons is clumsier than using an unnamed class object: First, clients must first get a handle of the instance; second, the implementer of Singleton::instance() might need to consider concurrency.

So why and how would you choose a singleton over an unnamed class?

As an addendum, although the obvious definition of an unnamed class might be

class {
    // ...
}single;

I could as well define it like so:

#ifndef NDEBUG
class Singleton__ {   // readable error messages,
#else
class {               // unnamed, clients can't instantiate
#endif
    // ...
}single;

with the latter approach having the advantage of readable compiler error messages but not being a singleton in debug mode.

+1  A: 

changing the code like that even if it probably shouldn't affect code generation is a terrible idea. sooner or later someone is going to make a minor tweak that generates different code in debug or release, and then you have release crashes that you can't replicate in debug builds.

Dustin Getz
A: 

if (besides error verbosity) there is no behavior difference, a global instance requires 1 extra LOC, a singleton will require a bunch of nontrivial boilerplate. KISS

Dustin Getz
+2  A: 

The singleton class you can declare in a header and implement in a cxx, and therefore share across cxx files. You can't do that with the unnamed class, since each cxx will try to have its own instance of the object.

David Norman
+7  A: 

I think the most important reason is that you cannot put an unnamed class in namespace scope. So, the following is not valid (gcc accepts, but warns. comeau doesn't accept in strict mode):

class { } single;
int main() { }

The type of single has no linkage because there is no way to declare its name in another scope referring to it (precisely because it has no name). But using it to declare single, which has linkage (external here) is not valid (3.5/8). single has to be defined locally in main where it will have no linkage. You also cannot pass single to function templates and it can't have static data members (because there is no way to define them). All those restrictions make it more or less not applicable as a substitution for a singleton.

Johannes Schaub - litb
Apparently the next standard will allow for unnamed types as template parameters: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2657.htm
wilhelmtell
yeah, they want to allow it. i think a major factor for them to allow it is the fact that it will also have lambdas, which are effectively objects of unnamed types. not being able to pass lambdas to templated functions would be a pity.
Johannes Schaub - litb
that reason alone is enough, definitely. i can't imagine using standard algorithms without lambdas (no wait, i can). :)
wilhelmtell
+1 litb. Seems like hardly a week goes by that I don't discover a new dark corner in C++...
j_random_hacker
You mean "the type of single", not obj.
Carlos A. Ibarra
errm, right. that happens when you change names and forget to change the text :) also changed "declare its identifier" back to "declare its name". i think that's the better term. "name" puts a meaning to an identifier (here, the name is an identifier naming a type). the standard seems to agree too.
Johannes Schaub - litb
+1  A: 

Though convenient, singletons are generally a bad idea. See this page for a replacement design.

Head Geek
+3  A: 

Surely the main reason for using singleton objects in C++ is to give you some control over the initialization order, by using 'lazy construction' within your instance method?

As an example, much of my code uses a logger singleton where log messages are written to. This started many moons ago as a good old 'global', but after being bitten by attempting to use it before construction, it's now a singleton:

before...

logger.write("Something bad happened..."); // crash if logger not constructed

...after

 Logger &getLogger()
 {
   static Logger logger_;
   return logger_;
 }

 getLogger().write("Something bad happened...");

I've read the regular "singletons are bad" posts, but havn't seen anyone suggest a better alternative for C++.

Roddy
Singletons are NOT generally bad! One simply needs experience with SW architecture to decide which of the components should be made a singleton. Using a singleton should be a conscious design choice, nothing more and nothing less.
Thorsten79
Singletons are *generally* bad. They are often used when they don't fit the requirements. (Singletons are for when it *will* cause problems to have more than one instance and when you *need* global access to the object.
jalf
Roddy's code is not strictly a singleton though, because it doesn't prevent me from creating multple loggers if I want to. (And I think this is a very good thing).So you're already using the "better alternative". ;)
jalf
+1  A: 

From your question I can see that you don't really understand the nature and purpose of Singleton pattern.

You use singleton if you want to have global object accessible by many 'clients' and you want to be sure only one instance of this object is created. Take for example a logger object. You want to be able to log from any part of your code but there should be only one logger in your project. This is a perfect place for singleton.

Your example looks as if you create a local object with small scope. For this singleton is not needed. It makes code much clearer and easier to read though.

zarzych
No, the unnamed class object is global. All I need to do is place the definition in a header file and include it wherever I want it.
wilhelmtell
You can use it this way but there are some limitations as litb said.
zarzych
A: 

use singletons. use const. initialize them all in one god class. be aware of and avoid the static initialization order fiasco: http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.12

Ray Tayek