C++ Singleton VS. Global Static Object

Difference between static class and singleton pattern?

What makes you say that either a singleton or a static method isn't thread-safe? Usually both should be implemented to be thread-safe.

The big difference between a singleton and a bunch of static methods is that singletons can implement interfaces (or derive from useful base classes, although that's less common, in my experience), so you can pass around the singleton as if it were "just another" implementation.

static object vs singleton class object in c++?

The main difference between a singleton and a static object is that the singleton guarantees that there can only be one instance of a particular class type, whereas a static object is only a single instance of a particular type. This means that the fundamental difference is whether it makes sense for the class to have multiple instances or not. For example, let's say that you have a factory that builds widgets.

class WidgetFactory {
public:
int numberOfWidgetsBuiltInTheWholeApplication();
// returns number_of_widgets_built
std::shared_ptr<Widget> build();
// increments number_of_widgets_built
private:
size_t number_of_widgets_built;
};

Let's also assume that we want to guarantee that we can determine the number of Widgets that were created in the entire application, and enforcing that there is only one WidgetFactory is an easy way to do this. This is where we would use a singleton. If we were to just use a static object, like this:

WidgetFactory& theWidgetFactory()
{
static WidgetFactory widget_factory;
return widget_factory;
}

we would have no guarantee that theWidgetFactory().numberOfWidgetsBuiltInTheWholeApplication() was actually the real total, since someone else could come along and make their own WidgetFactory instance.

However, if we make WidgetFactory be a singleton, we now have that guarantee. We could do that perhaps by making the constructors private:

class WidgetFactory {
public:
int numberOfWidgetsBuiltInTheWholeApplication();
std::shared_ptr<Widget> build();
private:
WidgetFactory();
WidgetFactory(const WidgetFactory &); // not implemented
friend WidgetFactory& theWidgetFactory();
};

Now only theWidgetFactory() function is allowed to create the instance. There are other ways that we could make numberOfWidgetsBuiltInTheWholeApplication() function properly without using a singleton, but perhaps in some situations that solution is more complicated or has other downsides.

Singleton instance as static field vs. static variable in getInstance() method

What are these trade-offs?

This is the most important consideration:

The static data member is initialized during the static initialization at the start of the program. If any static object depends on the singleton, then there will be a static initialization order fiasco.

The function local static object is initialized when the function is first called. Since whoever depends on the singleton will call the function, the singleton will be appropriately initialized and is not susceptible to the fiasco. There is still a - very subtle - problem with the destruction. If a destructor of a static object depends on the singleton, but the constructor of that object does not, then you'll end up with undefined behaviour.

Also, being initialized on the first time the function is called, means that the function may be called after the static initialization is done and main has been called. And therefore, the program may have spawned multiple threads. There could be a race condition on the initialization of the static local, resulting in multiple instances being constructed. Luckily, since C++11, the standard guarantees that the initialization is thread safe and this tradeoff no longer exists in conforming compilers.

Thread safety is not an issue with the static data member.

Which approach is better?

That depends on what your requirements are and what version of the standard you support.

Singleton class vs. class with static member

The main differences are simple things like:

  • with a singleton you can pass around the object for delegates and callbacks
  • with a singleton you can implement interfaces and derive it
  • with a singleton you can use a factory pattern to build up your instance

If you don't need any of them, as with global functionality that must be accessed all around your code then you can go with static methods.

I personally prefer using static methods unless I have an explicit reason to use a singleton instance (such as having a common interface but different implementations).

Mind the fact that refactoring static methods to a singleton instance is quite a straightforward process so if you ever find the need for the latter you will refactor it easily (then you have the C preprocessor, a single #define would be almost enough).

Singleton VS static(class) variables

tl;dr

Option 1 (class or struct) when you store mutable state because you need other instances.

Option 2 (scoped global variables) when you want to store static variables because it's faster and uses less memory.

Singleton Class (or struct) with variables

Global state is generally considered a "bad thing". It's hard to think about, causes problems but is sometimes unavoidable.

  • Create a class if you ever want to have multiple SomeManager instances.
  • A singleton can be good default instance but there may be edge cases where you want to have separate behavior (testing).
  • Dependency Injection... is big topic that is relevant if SomeManager is storing global state.

Static Variable

  • Always use when the someVariable is a constant.
  • Does not require extra storage for static var sharedManager = SomeManager(); you use only the memory which you actually need.
  • Slightly faster because you do not need to load sharedManager into memory then access it's member someVariable. You straight up access someVariable.

Bonus Tip:

In Option 2 you can create SomeManager even though it doesn't do anything. You can prevent this by turning SomeManager into an enum with no cases.

enum SomeManager {
static var someVariable: String?
}

You can still do this:

SomeManager.someVariable

but you can't do this

let manager = SomeManger()

Singleton - Impl. using static class member vs. static member variable

When you put a static variable inside a function it is created the first time the function is called so it is guaranteed to have been instantiated to all callers of the function.

Members that are declared static could be instantiated before or after you call your function because the initialization order between translation units is undefined. So a global object or static object could try to access a static member before its been initialized by the runtime system.

So to your questions:

  1. Can we consider both impl. as a valid impl. of the design pattern?
  2. Are both, functionally, the same?

No. Using a static member is dangerous because a caller to SingletonCSM::GetInstance() can access a non-created object if the nullptr initialization has not taken place before the call. The static function method is the recommended method because it guarantees initialization has completed for every caller.

I just don't understand what was the problem and why was it solved?

In your case moving to the more dangerous method appears to have stopped your crash. I can not explain why that is. But you may not have removed the problem, it may be that you have undefined behavior elsewhere that has simply stopped manifesting in this case but that may resurface later with a different change.



Related Topics



Leave a reply



Submit