1

I implemented the Singleton design pattern in my code.

Suppose it is:

class Singleton
{
  Singleton () {}
  static Singleton* s;
public:
  static Singleton* Get () {
    if (!s)
      s = new Singleton ();
    return s;
  }
};

What puzzles me is the 'initialization' of this pattern. In the .cpp I put:

SingletonPointer* SingletonClass::s (0);

But I don't understand how is it possible to access define s, as it is private. How's that possible?

TIA, Jir

Jir
  • 2,985
  • 8
  • 44
  • 66

5 Answers5

7

The best way you can use the Singleton pattern is to not use it at all.

A brief summary of why Singletons are bad:

  1. They are globals with special restrictions. Globals are bad enough for their own reasons; making them singletons just amplifies the badness.
  2. If you really need only one instance of an object, then just make one. If you need a special device to ensure you don't make more than one, then there's something wrong with the semantics of your code. Making it a singleton doesn't fix the problem, it just papers over it with new problems.
  3. Singletons don't play nice with threads. Threads are hard enough. Don't make them harder.

Using a Singleton doesn't solve any problem. It just applies false semantics to existing code, makes future extensions of that code difficult or impossible (what if you need two tomorrow?), and adds new problems. Long story short, just don't use them.

John Dibling
  • 99,718
  • 31
  • 186
  • 324
  • That is so true. I had an article that pointed out many reasons to avoid it. If i can find it i'll add it to my comment later. – RedX Apr 12 '11 at 14:03
  • 2
    @RedX: I'd be interested in such an article, I know of many shortcomings but it would be nice to have them somewhat formalized for future references :) – Matthieu M. Apr 12 '11 at 14:16
  • I'd love to see what are the arguments against it! – Jir Apr 12 '11 at 14:17
  • @Jir: Singletons and the evils they bring have been discussed ad-nauseaum both on SO and the Internet at large. Do a little searching. – John Dibling Apr 12 '11 at 14:27
  • @Jir: I'm am composing a list of links for you. – John Dibling Apr 12 '11 at 14:32
  • 1
    @Jir: Here's one link that will send you off in to many directions. http://jalf.dk/blog/2010/03/singletons-solving-problems-you-didnt-know-you-never-had-since-1995/ – John Dibling Apr 12 '11 at 14:39
  • 1
    But don't be mislead. Singleton is a pattern, like any other. It can be misused, but there are also cases where it is the most appropriate solution. – James Kanze Apr 12 '11 at 15:04
  • @James Kanze: It introduces problems without solving any. That makes it an anti-pattern as far as I'm concerned. Do you have an example of a situation where it is the most appropriate solution? – Mike Seymour Apr 12 '11 at 15:20
  • @James: I'll agree that there are situations where they are appealing. The clearer, in my mind, is logging. You don't want to have to clutter your API with a "Logger" argument, it's a pure debugging tool and not part of the "logic" of the functions. Do you have other examples of when it is appropriate ? I've already heard of "connections" and "it models a unicity" but they never really convinced me. – Matthieu M. Apr 12 '11 at 15:20
  • @Matthieu: you can define a globally-accessible logger without also arbitrarily preventing other instances. – Mike Seymour Apr 12 '11 at 15:23
  • @Mike: Well, it's not like using a Singleton restricts much :) You can still have other loggers (of a different class) etc... But I get it that your comment was most focused on *enforced unicity* while mine was more about *global variables* :) Amazing that such a "pattern" can accumulate so much flows :D – Matthieu M. Apr 12 '11 at 15:27
  • 2
    @Matthieu: Indeed, I was arguing against the Singleton "pattern", not the use of globals (which I agree is occasionally a good solution). I have never heard of a valid case for preventing multiple instances of a class, nor seen Singletons used as anything other than globals in disguise; I would be interested if anyone has an example. – Mike Seymour Apr 12 '11 at 15:34
  • 1
    @James: Please elaborate: Under what circumstances is a Singleton the most appropriate solution in a well-designed system? – John Dibling Apr 12 '11 at 15:34
  • Anytime what you're modelling is best represented as a unique object. They'll typically be manager type objects: LogManager, ConfigurationManager, etc. which ensure a common interface to a common resource, shared by all of the components and subsystems. (If someone modifies the log configuration, for example, you don't want to have to track down 100's of instances to update them.) – James Kanze Apr 12 '11 at 15:50
  • Another reasonable case: temporary files. You want to be sure that they are deleted on exit (unless you've passed in a special option to not delete them, for debugging purposes). A singleton seems to be the most reasonable solution here, as well. – James Kanze Apr 12 '11 at 15:51
  • 2
    @James: I disagree. In this instance, my assertion that "if you only need one, then just create one" applies. The logger object will often be owned by some Application-type object, which you only create one of. You don't need to go looking for it. Just do `my_app->GetLogger()->DoTheThing();` – John Dibling Apr 12 '11 at 15:52
  • @James: re: temporary files. If you have more than one temp file, then by definition this can't be a singleton. Unless you have some kind of `AllTempFilesDeleter` class which maintains a list of temp files to delete. But if youre doing that, why not just let a bunch of file smart-pointers (RAII objects) fall out of scope and delete the owned file? – John Dibling Apr 12 '11 at 15:54
  • @Mike A singleton doesn't introduce any more problems than any other pattern. Misuse a pattern, or use it where it isn't appropriate, and it introduces problems. Use it correctly and where appropriate, and it solves them. – James Kanze Apr 12 '11 at 15:56
  • @John Dibling If you're using temporary files, you need a temporary file manager of some sort; you want to create a separate directory to put them in (for security reasons, if nothing else), and you need to clean up that directory, as well as any of the files in it, when you exit. – James Kanze Apr 12 '11 at 15:57
  • @James: Sure, but you don't need a Singleton for that. – John Dibling Apr 12 '11 at 15:59
  • @John Dibling On long running programs, it's a imperative that there be only a single instance of the log manager, and that it can be easily found by everyone. All your suggestion does is move it out into a singleong Application object (which I've never found necessary). – James Kanze Apr 12 '11 at 15:59
  • @James: The `Application` object isn't a singleton. It's a normal object that has only been created once. – John Dibling Apr 12 '11 at 16:01
  • @John Dibling There are other solutions, obviously. Less effective and more error prone, but they do exist. Why not use the correct tool for the job? – James Kanze Apr 12 '11 at 16:03
  • @John Dibling `The Application object isn't a singleton` So how do you find it when you need it? It registers itself somewhere? In a singleton? Why all the extra work, with the added risk of errors, when there is a simple, effective and well known solution. – James Kanze Apr 12 '11 at 16:05
  • @James: I may be wrong, but you seem to be equating the Singleton anti-pattern with the use of globally accessible objects. If you are arguing that global objects have their (occasional) uses, then I agree. If you also have an example of where a Singleton (that is, the thing that bizarrely combines a globally-accessible object with a mechanism for preventing other objects of the same type) is appropriate, then I'd be very interested to hear it; I have never encountered such a situation. – Mike Seymour Apr 12 '11 at 16:11
  • @James: Just saying something is a less effective solution doesn't make it so. I have provided a number of reasons why Singletons are bad, and links to many more in-depth explanations. You have up to this point not refuted any of the anti-Singleton points, or provided any pro-Singletons points aside from just saying "Singletons are good." – John Dibling Apr 12 '11 at 16:12
  • 1
    @James: Another post about why singletons are bad, better said than mine: http://stackoverflow.com/questions/1020312/are-singletons-really-that-bad/1020384#1020384 – John Dibling Apr 12 '11 at 16:13
  • Singletons are bad. If you want a global, make a global. Don't make it a singleton. There is nothing "correct" about a singleton, and it is *less* effective and *more* error prone than the alternatives (try implementing a thread safe singleton. In the end, you'll be left with a singleton that merely *looks* thread safe, while imposing a performance penalty due to the excess locking. – jalf Apr 12 '11 at 16:31
  • 1
    @James: it's easy to say "use singletons where appropriate", but so far, you've only provided examples where a *global* would be appropriate. Our claim is that a global may sometimes be appropriate, but a singleton isn't. Can you come up with a case where a singleton is a better choice than a global? – jalf Apr 12 '11 at 16:32
  • 1
    Just to dispute your "it is imperative that there be only a single instance of the log manager", *no*, it isn't. It is imperative that all of your code can *reach* the global log manager, but there's no harm in creating another somewhere in the code. It may even be beneficial (think of unit testing. Each test may want to create its own new log manager, rather than reuse the one that may have been dirtied by a previous test). So in that case, a global might be reasonable, but a singleton only makes your code harder to test. It is not an appropriate tool there. – jalf Apr 12 '11 at 16:34
  • `Just to dispute your "it is imperative that there be only a single instance of the log manager",` That's not disputable, or negotiable. It's part of the requirement. All logging must respect the current configuration, and the specifications are quite clear: there is only one current logging configuration. And you cannot ever use a global variable as logging manager, because of order of initialization issues. – James Kanze Apr 12 '11 at 18:31
  • @jaif A global cannot ever be used as a logging manager. You can't control the order of initialization of a global. And once you've added the code to ensure initialization before first use, and to ensure that there is never more than one, and to ensure that it can be reached from everywhere, you've implemented a singleton without calling it one. – James Kanze Apr 12 '11 at 18:35
  • Re: temporary file manager; you do need a singleton, because each instance will create its own new directory, and the program specifications say that you're only to use a single directory for temporary files. (More generally, if the program requirements say you must never have more than one of `x`, then a singleton is a convenient way of enforcing this. And program requirement do say this about certain things.) – James Kanze Apr 12 '11 at 18:38
  • Concerning the article that John cited: the first sentence says almost exactly what I've been saying, in different words. 95% is obviously not meant to be an exact figure, and the two issues he cites aren't independent, so the final figure he uses is probably off somewhat. But it still leaves 0.25% of all classes which should be singletons. About 2 or 3 in a smallish project. Which sounds about right. (I've cited two or three examples. They're valid, but I don't think there are many more.) – James Kanze Apr 12 '11 at 18:47
  • @John Dibling `I have provided a number of reasons why Singletons are bad, and links to many more in-depth explanations.` Where? The only reason you've given here is that you don't like themm, and a vague claim that they're error prone (which hasn't been my experience). If I've not refuted any of your points, it's because I've yet to see any technical arguments to refute. – James Kanze Apr 12 '11 at 18:50
  • @James: I think jalf has given pretty good reasons as to why one suddenly might want to have more than one logging manager, whereas you said little but "no, never". Having seen many global variables (Singletons or not) of which suddenly more than one instance was needed (to the dismal of the developers who had to clean up the global mess), I don't find that very convincing. Further, the initialization order fiasco of global variables is a very good reason to not to use globals. Another is that they hide dependencies. – sbi Apr 12 '11 at 19:29
  • So lets for a moment entertain the idea that a Singleton _might_ be justified in 0.1% of all cases. Still, that would mean they are not justified in the overwhelming majority of cases where they are currently used. They have done much more harm that way than any good they could ever make, so, even assuming that there is indeed that 0.1% of cases, it is much easier to propagate other means to deal with those than having to deal with the mess the propagation of Singletons has left us with. – sbi Apr 12 '11 at 19:31
  • I can think of one case where a global cannot replace a singleton: a thread-local singleton (which is not exactly a singleton, since it has one instance *for each thread*). Sure, just about any modern compiler has some sort of thread-local storage modifier (which will soon be [standardized](http://en.wikipedia.org/wiki/C%2B%2B0x#Thread-local_storage) anyway), but that works only if you're writing a DLL and your functions are being called from threads created before your DLL was loaded. In that case, Thread-local globals just won't do. – Boaz Yaniv Apr 12 '11 at 23:03
  • @sbi The issue is simply one of program requirements. If the requirements involve logging, with a single dynamic configuration of the log (a frequent case in server software), then anything which causes duplicate, possibly different copies of the configuration to exist violates the requirements. That it might be more convenient for the developer to ignore the requirements is **not** an acceptable argument. – James Kanze Apr 13 '11 at 08:14
  • 1
    @James: I know you have a lot of experience, and maybe that's indeed contradictory to mine, or we're just interpreting the same data differently, but after almost 15 years in the industry I'm at the point where I don't believe anyone who says "we'll only ever need one of these", be they a programmer knowing what they do or a manager relaying requirements. Too often I have seen such requirements fall down at some manager's whim. IME it only takes one well-paying customer to throw overboard anything you thought was fixed in some project, including everything PM has sworn will never change. – sbi Apr 13 '11 at 09:24
  • 1
    And then there still is @jalf's very fine argument regarding testing. Code using globals and singletons is hard to test, and for testing you might want to have a different logger instance for every test run. Yes, this can all be done using Singletons if you're prepared to jump through some hoops, but why first limit yourself, just to undermine those limitations later on, when not limiting yourself would be so much easier? – sbi Apr 13 '11 at 09:25
  • @sbi There are a few cases. Two that show up a lot are the logging configuration (which often has to be global) and the directory in which you put temporary files. I also use a singleton in my implementation of command line parsing---and if there's one thing I'm 100% sure of, it's that I'll never have more than one command line:-). (I totally agree that such cases are rare, and that you usually should provide for more than one, even if the spec says that only one is needed now.) – James Kanze Apr 13 '11 at 10:58
  • 1
    @James: If you create a second logging gizmo, will your computer explode? If not, you don't *need* a Singleton. If you only want one log and have it easily accessed, then *only create one* and make it a global. – John Dibling Apr 13 '11 at 15:36
  • @John If I create a second log configuration, the code will not be conformant to the requirements. – James Kanze Apr 13 '11 at 17:21
  • 3
    @James: Then don't create a second one. – John Dibling Apr 13 '11 at 17:26
  • @John But I still need the singleton logic to handle order of construction issues for the first. And of course, trust is nice, but verification is better---if having more than one breaks the program, and there's an easy and effective way to ensure that this can't happen, I'd be foolish not to use it. – James Kanze Apr 13 '11 at 18:21
  • 1
    @James: Both problems solved. `class Logger {}; class App { public: Logger log_; } the_app; /*...*/ the_app.log_.DoIt();` Trust no longer an issue if you wrote the code for `App` – John Dibling Apr 13 '11 at 19:17
  • @John This doesn't solve the problem of order of initialization (or rather, it defers it to initializing `App` and ensuring that there is only one instance of `App`). And it introduces an unnecessary complication, and an additional class for nothing. – James Kanze Apr 14 '11 at 08:10
  • 2
    @James Kanze: you can solve the initialisation order problem by accessing it via a global function, in which it is either a static variable (with some caveats about thread safety [which will be fixed in C++0x, and are already fixed in most compilers] and destruction order), or created as in the question (addressing thread safety issues if necessary). This is a completely separate issue to preventing multiple instances, and you still haven't provided an example of why you'd want that apart from "because some lunatic put it in the specification". – Mike Seymour Apr 14 '11 at 09:04
  • @james: ok I give up.i think you're just being stubborn now. – John Dibling Apr 14 '11 at 11:14
  • @John Given that I have a solution that works, and has worked in the past, and that no one has been able to give any real reason why it's bad, or propose something better, yes, I'll be stubborn. – James Kanze Apr 14 '11 at 14:30
  • @James. That's the same argument C users give for why they prefer C over C++. And it's the same assembler programmers used to use for preferring assembler over C. Sorry, but I'm not convinced at all. – sbi Apr 14 '11 at 18:40
  • John has referred to the most obvious way of preventing not to have a second instance of some class: create only one. That is simple and elegant, works, allows to exactly define the moment the object is instantiated (thus no initialization order woes), and makes it much easier to test the code than using a Singleton would. And if you really only have two Singletons in an application, it shouldn't be hard to keep those under control. – sbi Apr 14 '11 at 18:40
  • A Singleton adds complexity, by introducing a set of additional rules for a type. That complexity must be warranted, so using Singletons should be done for good reasons only. And "that's the way I've always done it" isn't good enough a reason in my book. – sbi Apr 14 '11 at 18:43
  • @sbi The "additional rules for a type" are present in the requirements specification; you can't ignore them. John has proposed using code review to enforce them, rather than letting the compiler do it for you (or not enforcing them at all---I'm not sure which). – James Kanze Apr 15 '11 at 09:01
  • 1
    @James: Your biggest problem is that the requirements specification is badly written. Its purpose is to define the behaviour of the production system, not to dictate how it should be designed, nor to place arbitrary restrictions on how it can be tested. Requirements can and do change, and any that have been enforced by the structural design of the system will be very expensive to change. As for enforcement by the compiler, noone will accidentally create a new object rather than using the one provided, and trying to automatically prevent deliberately perverse behaviour is a losing battle. – Mike Seymour Apr 16 '11 at 12:23
  • @James: You're falling into the old habit of ignoring most arguments and countering only a very few. I never liked it when you did that. And I've flagged your answer to Mike as offensive. I'm not a native speaker, so I could be wrong, but _I consider "you're not in touch with reality" to be insulting_. – sbi Apr 18 '11 at 10:25
  • @sbi It's no more insulting than e.g. stating that the requirement specification is badly written, and it corresponds closer to the facts. The requirement specification is written by the people who actually have to manage the system, once I deliver it, and they have very good reasons for not wanting to contend with multiple different logging configurations. Pretending that you can just force clients to accept anything you find convenient, for whatever reasons, isn't realistic. – James Kanze Apr 18 '11 at 10:38
  • @James: Well, as it seems, the moderators were my opinion about your reply to Mike, not yours. And that's not even taking into account that you're knocking down a strawman here. (To wit: nobody said you should force your clients to do anything.) – sbi Apr 18 '11 at 22:19
  • @James: I think it's time to wrap up the discussion. When is a singleton appropriate? When you've been given a specification that arbitrarily demands than you use one. When is it not appropriate? When you want to test your components in isolation. When there's the slightest chance that a future iteration might require more than one instance. When you want to ease maintenance by making all dependencies between components explicit, avoiding invisible coupling. When you want a structured, flexible design that won't get in the way of adapting to future requirements. – Mike Seymour Apr 19 '11 at 09:36
  • @James: re "Pretending that you can just force clients to accept anything...": It's a two-way relationship, and there's always the possibility of negotiation. A reasoned argument might convince them that the results could be better without strange design restrictions; even if that negotiation fails, that is only a reason to use a bad design pattern for that project, not to endorse it for general use. – Mike Seymour Apr 19 '11 at 09:43
  • @Mike When is a singleton appropriate: when it is the best solution to the problem. When is it not appropriate: when it is not the best solution to the problem. That pretty much sums it up. A singleton doesn't create any particular problems in testing---I've done extensive unit tests in projects which contained singletons. The dependency on the singleton is explicit, and the singleton doesn't get in the way of adapting to future requirements. It's not often the best solution, but it sometimes is. – James Kanze Apr 19 '11 at 10:39
  • @Mike I think you misunderstand the requirements specification I'm talking about. The requirements aren't a "strange design restriction". The requirement is designed to make managing the system easier. It's a valid requirement, and I'd insert it myself were the roles reversed. I'm not endorsing the singleton, or any other one pattern, for general use. Just when the pattern is appropriate. – James Kanze Apr 19 '11 at 10:41
  • @James: "The dependency on the singleton is explicit" - at the point of use, not at the point of initialisation of an object that uses it. – Mike Seymour Apr 19 '11 at 17:47
  • 1
    @James: "the singleton doesn't get in the way of adapting to future requirements" - when you need to introduce multiple instances, you will need to go through all the code that accesses the singleton - potentially every function in the system. With a structured design, you just change the object initialisation code to provide access to the correct instance. – Mike Seymour Apr 19 '11 at 17:50
  • @James: "It's not often the best solution, but it sometimes is" - the only example you've given is a desire to prevent people from jumping through hoops to wilfully break a requirement. The requirement that "all production code use the same logging facility" is easily obtained using a conventional structured design, creating a single instance and providing a reference to all objects that need it. To ignore that instance and create your own will require both ignorance of the requirements, and lack of basic common sense; no amount of enforcement at the design level can help to prevent that. – Mike Seymour Apr 19 '11 at 17:54
  • @James: "A singleton doesn't create any particular problems in testing" - how do you prevent your tests from writing to the production logs? You will need some way to configure your singleton depending on the environment. Is this done at runtime? If so, how do you prevent arbitrary code from changing it in production? Is it done by reading the configuration from the environment? That introduces quite a lot of extra complexity, and yet another facility that everything depends on. With a structured design, simply create a production instance in production, and a test instance in test. – Mike Seymour Apr 19 '11 at 18:03
  • @Mike The singleton is a defensive measure (partially---in C++, it also solves the order of initialization problem). It's not essential, just like making member variables private instead of public isn't essential. The risk of an error if you don't use it is fairly small, but since you need 99% of the code for it anyway in order to ensure order of initialization, why not protect yourself? (I sort of agree with the "lack of common sense" comment. Most singleton's have semantics such that it wouldn't occur to a programmer to create one themselves.) – James Kanze Apr 19 '11 at 18:10
  • @Mike With regards to testing, at least with regards to the log, you simply provide a different configuration file which the singleton reads. Configuration is handled similarly. No need for a separate instance. – James Kanze Apr 19 '11 at 18:12
  • @James: "I think you misunderstand the requirements specification I'm talking about" - I may have misunderstood you when you said 'The "additional rules for a type" are present in the requirements specification', implying that the requirements explicitly called for the use of a singleton. If that is the case, then the requirements are badly written; you will need to use a singleton, but that does not make it a good choice. If it isn't an explicit requirement, then there are more conventional designs which will achieve the requirement without coupling a single instance to the entire system. – Mike Seymour Apr 19 '11 at 18:13
  • 1
    @James: the best solution to the static initialisation fiasco is to avoid static objects altogether, and create everything explicitly after `main` has started. I agree that other solutions are "99% of the code" for a singleton (the only remaining evil being to make the constructor private); that still doesn't justify the ramifications of coupling a single instance to everything just to prevent a mistake that nobody will make anyway. – Mike Seymour Apr 19 '11 at 18:17
  • @James: Making variables private prevents someone *accidentally* breaking a class invariant, and leaving the system in an invalid state that could be very difficult to debug. Some class invariants may be subtle, so it's better not to expect users of a class to understand all the potential pitfalls of its implementation details, but rather expose an interface that's safe to use. A singleton prevents the user of the class from *deliberately* breaking a high-level requirement (that's independent of the class itself), at the cost of preventing test code from legitamately creating multiple objects. – Mike Seymour Apr 19 '11 at 18:25
  • @James: "you simply provide a different configuration file" - so you also have a configuration file reader coupled to everything else in the system. With a structured design, test code will not need this either; it can simply create either a dummy log facility, or one configured for a test environment, without depending on anything other than the class under test. – Mike Seymour Apr 19 '11 at 18:28
6

Static fields must have definitions besides their declaration. The declaration usually goes in the class declaration in the .h file, while the definition almost always goes in the .cpp file. The definition of static variables is a must, since they must be initialized to something.

But even though the definition is outside of the class body and even in an entirely different file, it doesn't mean it's not a part of the class. The SingletonClass:: makes it part of the class definition (as opposed to the class declaration), and therefore it can 'access' private fields.

The same goes for methods defined outside of the class body, for instance:

// A.h
class A
{
private:
    int b;
public:
    A(int x) : b(x)
    {}

    Do();
}

// A.cpp
A::Do()
{
    return b;
}
Boaz Yaniv
  • 6,334
  • 21
  • 30
  • Now it's clear. Thanks for the explanation. It didn't occur to me that we always do that when defining class methods. – Jir Apr 12 '11 at 14:14
2

In the initialization code, you're not accessing Singleton::s, you're defining it.

NPE
  • 486,780
  • 108
  • 951
  • 1,012
  • Point taken: it's about definition and not access. Still, how is it possible to define it outside the class if it is private? – Jir Apr 12 '11 at 13:59
2

The private variables can be accessed by all methods of a class. The only place you are accessing the s variable is in method Get() which belongs to the same class.

If you want to access the s from outside, you can't do it directly, but you have to call the Get() method (which is public) and that method will actually return s for you.

Usage:

Singleton * s = SingletonClass::Get();
Binus
  • 1,065
  • 7
  • 14
0

It is accessed from the outside via Get (if you give that the appropriate type). The fact that it is private doesn't prevent that method from returning a pointer to it. A member being private just prevents access to it by name.

Fred Foo
  • 355,277
  • 75
  • 744
  • 836