12

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

Adam Rosenfield
  • 390,455
  • 97
  • 512
  • 589
Alex Gaynor
  • 14,353
  • 9
  • 63
  • 113
  • 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 Nov 18 '08 at 04:10

7 Answers7

22

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
  • 951,095
  • 183
  • 1,149
  • 1,285
  • 1
    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. – richq Nov 18 '08 at 10:01
  • @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 Nov 18 '08 at 15:09
  • 1
    Random, undefined, cannot be determined at compile time... same difference. – richq Nov 28 '08 at 18:02
  • 2
    if I did like MyClass = MyClass() what would happen? – J.Doe Apr 21 '18 at 02:29
5

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
  • 257,169
  • 86
  • 333
  • 562
  • 6
    According to this logic, std::cout is a code smell as well. – rr- Aug 10 '15 at 12:58
  • @rr-: You should read ["Martin Fowlers" book on refactoring](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672/ref=sr_1_1?ie=UTF8&qid=1439219908&sr=8-1&keywords=refactoring+by+martin+fowler). – Martin York Aug 10 '15 at 15:19
  • @rr-: Or any of the millions of articles on [Global mutable state being bad](http://programmers.stackexchange.com/questions/148108/why-is-global-state-so-evil) – Martin York Aug 10 '15 at 15:20
  • @rr-: Or watch some of the [Google Talks about Global Mutable state being bad](https://www.youtube.com/watch?v=-FRm3VPhseI) – Martin York Aug 10 '15 at 15:21
  • 3
    I'm not sure how reasons for singletons being bad relate to my observation about `std::cout`. Is `std::cout` bad or not? If it's not bad, why? (Note - I assumed it isn't bad, because if it was, people would have come up with something different.) – rr- Aug 10 '15 at 15:27
  • @rr-: Like all globals its a smell. A smell does not mean necessarily bad it means you should take another look to make sure. – Martin York Aug 10 '15 at 17:24
  • Globals are perfectly fine for many uses. Much more dangerous thing is if they now include non-builtin static variable in the signleton without knowing about static initialization order fiasco. – Igor Levicki Jan 14 '18 at 14:52
  • @IgorLevicki: The static order initialization problem is easily solved (and is not even a problem (as long as you understand the issue) let a lone a fiasco). – Martin York Jan 14 '18 at 19:24
1

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
  • 4,103
  • 3
  • 26
  • 30
1

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
  • 299
  • 1
  • 2
  • 6
0

the Singleton pattern is what you're looking for.

Joel Martinez
  • 46,929
  • 26
  • 130
  • 185
0

The simplest and concurrency safe implementation is Scott Meyer's singleton:


#include <iostream>

class MySingleton {
public:
    static MySingleton& Instance() {
        static MySingleton singleton;
        return singleton;
    }
    void HelloWorld() { std::cout << "Hello World!\n"; }
};

int main() {
    MySingleton::Instance().HelloWorld();
}

See topic IV here for an analysis from John Vlissides (from GoF fame).

Cyber Oliveira
  • 8,178
  • 4
  • 28
  • 18
  • 1
    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 Nov 18 '08 at 05:51
  • 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 Nov 18 '08 at 07:02
  • I agree with @Dmitry: until the standard provides a way to deal with the presence of threads, it's unsafe. – xtofl Nov 18 '08 at 07:57
0

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

deft_code
  • 57,255
  • 29
  • 141
  • 224