wilhelmtell
wilhelmtell

Reputation: 58685

How do you choose between a singleton and an unnamed class?

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.

Upvotes: 3

Views: 3273

Answers (8)

Johannes Schaub - litb
Johannes Schaub - litb

Reputation: 507165

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.

Upvotes: 8

Ray Tayek
Ray Tayek

Reputation: 10003

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

Upvotes: 0

zarzych
zarzych

Reputation: 981

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.

Upvotes: 1

Roddy
Roddy

Reputation: 68054

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++.

Upvotes: 4

Head Geek
Head Geek

Reputation: 39878

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

Upvotes: 1

David Norman
David Norman

Reputation: 19889

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.

Upvotes: 2

Dustin Getz
Dustin Getz

Reputation: 21801

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

Upvotes: 0

Dustin Getz
Dustin Getz

Reputation: 21801

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.

Upvotes: 1

Related Questions