tags:

views:

2491

answers:

11

As the title says. How would I create an instance of a class that is globally available(for example I have a functor for printing and i want to have a single global instance of this(though the possibility of creating more)).

A: 

the Singleton pattern is what you're looking for.

Joel Martinez
A: 

This previous question is but one example of a singleton here on StackOverflow:

http://stackoverflow.com/questions/270947/can-any-one-provide-me-a-sample-of-singleton-in-c

Mark Ransom
A: 

Awesome thanks! I'll need to think about how this impacts the rest of the code, but I hadn't thought about implementing the singleton in C++.

Alex Gaynor
+1  A: 

As a slight modification to the singleton pattern, if you do want to also allow for the possibility of creating more instances with different lifetimes, just make the ctors, dtor, and operator= public. That way you get the single global instance via GetInstance, but you can also declare other variables on the heap or the stack of the same type.

The basic idea is the singleton pattern, however.

Mike Kale
+8  A: 

Going to all the effort of making a singleton object using the usual pattern isn't addressing the second part of your question - the ability to make more if needed. The singleton "pattern" is very restrictive and isn't anything more than a global variable by another name.

// myclass.h

class MyClass {
public:
    MyClass();
    void foo();
    // ...
};

extern MyClass g_MyClassInstance;

// myclass.cpp

MyClass g_MyClassInstance;

MyClass::MyClass()
{
    // ...
}

Now, in any other module just include myclass.h and use g_MyClassInstance as usual. If you need to make more, there is a constructor ready for you to call.

Greg Hewgill
Ugh. This will break if MyClass depends on some other global instance being initialised first, since the order of initialisation of globals is "random". Better to use regular class + (create a single instance) factory class.
rq
@rq: Its not random: see http://stackoverflow.com/questions/294270/how-do-you-call-a-constructor-for-global-objects-for-arrays-of-objects-and-for#294308
Martin York
Random, undefined, cannot be determined at compile time... same difference.
rq
A: 

Ah Greg, I think that solution is probably perferable, since that way I simply have a general name to use for that.

Alex Gaynor
A: 
Leonardo Constantino
it ISN'T concurrency safe. In C++ standard, static becomes "initialised" when constructor ends, so each thread that will enter Instance() method at the time of initialisation will cause singleton to be re-created,
Dmitry Khalatov
Dmitry Khalatov@ Technically correct. There are several simple solutions. a) Use gcc it has an explicit fix to deal with this (non standard). b) Create the object before any threads c) Use a lock inside the Instance() method.
Martin York
I agree with @Dmitry: until the standard provides a way to deal with the presence of threads, it's unsafe.
xtofl
Good to know! Thanks everyone.
Leonardo Constantino
A: 

Another advantage of greg's solution is that I can replace the object with a subclass of it, and that works correctly(since I use a pointer).

Alex Gaynor
A: 

Singleton is nice pattern to use but it has its own disadvantages. Do read following blogs by Miško Hevery before using singletons.

  1. Singletons are Pathological Liars

  2. Root Cause of Singletons

  3. Where Have All the Singletons Gone?

Swapnil
+3  A: 

First off the fact that you want global variables is a 'code smell' (as Per Martin Fowler).

But to achieve the affect you want you can use a variation of the Singleton.
Use static function variables. This means that variable is not created until used (this gives you lazy evaluation) and all the variables will be destroyed in the reverse order of creation (so this guarantees the destructor will be used).

class MyVar
{
    public:
        static MyVar& getGlobal1()
        {
            static MyVar  global1;
            return global1;
        }
        static MyVar& getGlobal2()
        {
            static MyVar  global2;
            return global2;
        }
        // .. etc
}
Martin York
A: 

I prefer to allow a singleton but not enforce it so in never hide the constructors and destructors. That had already been said just giving my support.

My twist is that I don't use often use a static member function unless I want to create a true singleton and hide the constr. My usual approach is this:

template< typename T >
T& singleton( void )
{
   static char buffer[sizeof(T)];
   static T* single = new(buffer)T;
   return *single;
}

Foo& instance = singleton<Foo>();

Why not use a static instance of T instead of a placement new? The static instance gives the construction order guarantees, but not destruction order. Most objects are destroyed in reverse order of construction, but static and global variables. If you use the static instance version you'll eventually get mysterious/intermittent segfaults etc after the end of main.

This means the the singletons destructor will never be called. However, the process in coming down anyway and the resources will be reclaimed. That's kinda tough one to get used to but trust me there is not a better cross platform solution at the moment. Luckily, C++0x has a made changes to guarantee destruction order that will fix this problem. Once your compiler supports the new standard just upgrade the singleton function to use a static instance.

Also, I in the actual implemenation I use boost to get aligned memory instead of a plain character array, but didn't want complicate the example

caspin