2

In Java I can create a Singleton like this (as long as it doesn't throw as exception):

private static Singleton m_this = new Singleton();

This is very convenient because it's inherently thread safe.

Can I do something similar in C++?

user1028741
  • 2,376
  • 4
  • 25
  • 51
  • See: https://ideone.com/whiUhA – Brandon Apr 07 '14 at 01:54
  • @CantChooseUsernames that way, you're getting a local copy of `instance` every time you call `getInstance`. – Paweł Stawarz Apr 07 '14 at 02:03
  • What? I'm getting the same exact instance.. It's static. I just forgot to make the function `getInstance` itself static is all. – Brandon Apr 07 '14 at 02:08
  • @CantChooseUsernames, I think it's not thread safe (in contrary to the Java line, which is...) – user1028741 Apr 07 '14 at 02:24
  • 1
    @CantChooseUsernames you're __not__ returning the static instance. You're returning a copy of it, since the function doesn't return a __reference__ in your code. – Paweł Stawarz Apr 07 '14 at 02:30
  • See the accepted answer for this question: http://stackoverflow.com/questions/11711920/how-to-implement-multithread-safe-singleton-in-c11-without-using-mutex – Lilshieste Apr 07 '14 at 04:19
  • 1
    Oh sorry @PawełStawarz I didn't notice that.. I guess my example is bad. +1 from me. I was trying to write what Martin J wrote as the answer. – Brandon Apr 07 '14 at 16:20

3 Answers3

3

One way of making a singleton with thread-safe initialization, guaranteed by the standard as of C++11. is:

class SomeSingleton {
  public:
    static SomeSingleton& instance() {
      static SomeSingleton instance_;
      return instance_;
    }

  private:
  SomeSingleton() {
    ...
  }
};

This is thread-safe, because local static variable initialization is thread-safe in C++11. The relevant standard document, N3485, says in section 6.7.4:

such a variable is initialized the first time control passes through its declaration; such a variable is considered initialized upon the completion of its initialization. [...] If control enters the declaration concurrently while the variable is being initialized, the concurrent execution shall wait for completion of the initialization.

with footnote:

The implementation must not introduce any deadlock around execution of the initializer.

You can abstract into a nice template base class with CRTP:

//Singleton template definition
template <typename TDerived>
class Singleton {
  static_assert(is_base_of<Singleton, TDerived>::value, "Singleton: unexpected Derived template parameter");
  public:
    static TDerived& instance() {
      static TDerived instance_;
      return instance_;
    }

  protected:
  Singleton() {
  }
};

// SomeSingleton definition, using the Singleton template
class SomeSingleton : public Singleton<SomeSingleton> {
  ...
};
Community
  • 1
  • 1
Martin J.
  • 4,748
  • 4
  • 21
  • 38
1

If by Singleton, you mean a real singleton (which I'm not sure is the same you gave an example of, because you still could create a second Singleton instance and assign it to a different variable), the answer is yes. You can create a singleton object using the factory pattern.

class factory;
class singleton{
   singleton(){}; // private constructor
   friend class factory;
};

class factory{
   private:
      static std::shared_ptr<singleton> object;

   public:
      static singleton& getSingleton(){
         if(object)
            return *object;
         object = new singleton;
         return *object;
      }
};

Instead of making a dedicated factory class, you could make getSingleton a static member function of singleton itself too. Just remember to make the constructor private, so the user can't create multiple copies.

Paweł Stawarz
  • 3,704
  • 2
  • 14
  • 26
  • That destructor on `factory` is very misleading. I'd have provided another `static` method for destroying the singleton. – yzt Apr 07 '14 at 01:57
  • @yzl you're right, a `shared_ptr` is way safer in this case. – Paweł Stawarz Apr 07 '14 at 02:01
  • @PawełStawarz, this solution is not thread safe (in contrary to the Java line in my question...), is there no way to create a thread-safe singleton inline (like in Java)? – user1028741 Apr 07 '14 at 02:26
  • @user1028741 if you want to make it thread safe, combine it with `std::atomic`: http://www.cplusplus.com/reference/atomic/atomic/ – Paweł Stawarz Apr 07 '14 at 02:32
1

Also, on top of answer given by Paweł Stawarz, I would add that copy constructor, move constructor (C++11), overloaded assignment operator and destructor should be private too.

class singleton{
   singleton(){}; // private constructor
   ~singleton(){}; // private destructor
   singleton(const singleton &src){}; // private copy constructor
   singleton(const singleton&& src){}; // private move constructor for C++11
   singleton& operator = (const singleton& src){return *this;} // private = operator
   friend class factory;
};

Being private, copy constructor, move constructor (C++11), overloaded assignment operator and destructor cannot be called from outside to clone an existing copy and also to destroy a copy just created.

Dr. Debasish Jana
  • 6,653
  • 3
  • 24
  • 55