tags:

views:

551

answers:

5

Is it compulsory to have a private destructor for a singleton class.

+1  A: 

All classes have a destructor. If you don't create one the compiler will do so for you. So your question can be reworded to: Does the destructor for a singleton class have to private?

The simple answer is no, it doesn't have to be.

A more interesting question: Is it a good idea to make the destructor of a singleton class private?

Yes, in general, it is a good idea. If you make it private then your client code won't call the destructor by accident. Calling the destructor would cause the singleton to fail for all clients as the instance would become invalid.

Mark Byers
If your singleton is never copied (which it shouldn't be, since that would make it no longer a singleton), it can never fall out of scope, which means the destructor can never be called in the first place (even accidentally).
Travis Gockel
@Travis: it can: `GetSingleton()->~CSingleton()`
MSalters
@MSalters, but who in their right mind would do such a thing? IMHO, any code that calls a destructor explicitly and isn't using placement new is highly suspect.
Michael Aaron Safyan
or less perverse: `p = GetSingleton()`, and `/* Momma told me to always delete my pointers:*/ delete p;`
Matthieu M.
@Matthieu: But a Singleton getter returning a _pointer_ simply is a case of bad interface design. (That is, unless you're in an environment where a naked dumb pointer means "don't worry about deletion", because everything worth worrying over is handled by smart pointers.) I'd expect a Singleton getter to hand me a reference.
sbi
The singelton object should never be returned from getInstance() as a pointer. It should be returned as a reference and then this problem is moot (even if internally it is dynamically allocated via new just return a reference). If done with a static method/function variable then the whole convept of actually needing to delete is removed.
Martin York
Actually, I tend never to expose my singletons, not even by reference. I just prefer the user to call `Object::Do(foo)` than `Object::GetInstance().do(foo)`... but then it's not as if we were using Dependency Injection down there.
Matthieu M.
+2  A: 

If the singleton is implemented as a variable at global scope, it must have a public destructor. Only public members are accessible at global scope.

If it's declared as a static member or static local within its own class, then the destructor may be private. The destructor is called from within class scope, where it is accessible, when the program exits. That is one way to enforce the object being a singleton. Do you need to strongly enforce that? If so, yes. It depends what you mean by "compulsory."

class A{
private:
    ~A() {}
public:
    static A &getGlobalA() {
        static A a2; // <- or here - better technique
        return a2;   // this is initialized upon 1st access
    };               // and destroyed on program exit

    static A a; // <- constructor, destructor accessed from here
};

A A::a; // <- but "called" from here in terms of control flow
Potatoswatter
The actual local `static` is one of the most convenient way. What is the effect of calling `getGlobalA` after `a2` has been destroyed (during the destruction of globals) ? I am afraid it would lead to UB.
Matthieu M.
@Matthieu m: See this article for a simple technique to mitigate this problem: http://stackoverflow.com/questions/335369/finding-c-static-initialization-order-problems/335746#335746
Martin York
+1  A: 

This might not be what you are looking for.. But for reference, I use it as follows:

// .h
class Foo {
public:
    static Foo* getInstance();
    static void destroy();
private:
    Foo();
    ~Foo();

    static Foo* myInstance;
};

// .cpp
Foo* Foo::myInstance = NULL;

Foo* Foo::getInstance(){
    if (!myInstance){
        myInstance = new Foo();
    }
    return myInstance;
}
void Foo::destroy(){
    delete myInstance;
    myInstance = NULL;
}

Then at the end of my program, I call destroy on the object. As Péter points out the system will reclaim the memory when your program ends, so there is no real reason. The reason I use a destroy is when Ogre complained that I hadn't released all the memory I allocated. After that I just use it as "good manner", since I like cleaning up after myself.

Default
When you explicitly provide a `destroy`, you also provide a leaky abstraction. You should look up Alexandrescu "Modern C++ Design" and take inspiration in `Loki::Singleton`.
Matthieu M.
You might want to register destroy with atexit.
Michael Aaron Safyan
What I can get from books.google.com is that *when destroying the singleton I should remove it at application's shutdown*. But I'm curious what you mean by leaky abstraction. Should i create a new question perhaps..? :) Would it still be leaky if I do it as Michael Aaron suggests?
Default
The problem is that you are opening up the code to a leak.The user of the singelton must know that they need to use destroy it and then insert the code at the correct place. Unlike Java, C++ allows a good developer to taking the responsibility of designing the class so it is hard to abuse (a feature of RAII). As a developer you should attempt to take up this mantel and try and build a singelton that does not require the user to understand the implementation to use it correctly. Requiring an explicit destroy is giving the user the opportunity to abuse the class (by not calling it).
Martin York
If you *need* to destroy it before the code completes, (i.e. exit() just wont't cut it) then using a singleton isn't what you want. Probably.
Chris Huang-Leaver
@Chris: yeah.. in school I learned what I wrote in this answer. The last months here on SO have tought me never to use singleton again :P So it might not be a problem after all. Thanks anyways
Default
@Michael Sadly, use of singletons in code is almost a cargo cult...
Chris Huang-Leaver
+1  A: 

You may return reference to your singleton instance.

class Factory : public IFactory
    {
    private:
        /**
        * This class should not be instantiated through its constructor. Since, it implements 
        * Singleton pattern.
        */
        Factory();      
    public:
        virtual ~Factory();
        /**
        * Accessor method for singleton instance.
        * \note use this static method to access to operations of this class.
        */
        static IFactory& instance(){
            if(!m_instance.get()){
                m_instance.reset(new Factory());    
            }
            return static_cast<IFactory&>(*m_instance);
        }
        /**
        * \see IFactory::create
        */
        virtual boost::shared_ptr<IConnector> create();
    private:
        /* Singleton instance */
        static boost::scoped_ptr<Factory> m_instance;

    };
baris_a
Apart from the fact that the `static_cast` is unnecessary (you can implicitly convert from derived to base), it's not too bad. There are issues with access after the destruction you should try to understand though.
Matthieu M.
I see no need for dynamic creation. Just create a static function variable and you will have the same functionality. With the advantage that you can control (to a degree) when it is destroyed so that you don't get access after it is destroyed.
Martin York
@Martin yes you are right but this is just an example for lazy initialization.
baris_a
@baris_a: As is using a static function variable.
Martin York
+1  A: 

No, and in general objects in C++ are not given private destructors. Keep in mind that Singleton means that there is only one instance, and so it is construction, not destruction, that needs to be controlled / prevented. Usually a singleton has a private constructor, a public destructor, a private static instance variable, and a public static singleton get / lazy construction function, although there are variations on that pattern.

Michael Aaron Safyan