4

What is the difference between:

class A { public: static const A& GetInstance() { static A a; return a; } }; 

and

class B { public: static const B* GetInstance() { static B* b = new B; return b; } }; 

? Is there a difference in the lifetime of the Singleton between A and B? the memory location of the object? any differences generally?

2 Answers 2

8

The lifetime of the object in these two cases is different. C++ guarantees that static local objects will be destroyed in reverse order to their construction. In both cases, construction will happen when GetInstance is first called.

However, in the second case, the variable b was assigned a pointer allocated with new. When b is removed from static storage, that memory will remain until the heap is finally torn down. At that stage it would be considered "leaked", and the destructor (if any) for B will never be invoked.

It would be better to implement the pointer-based approach like this:

class B { public: static const B* GetInstance() { static std::unique_ptr<B> b( new B ); return b.get(); } }; 

Now, B::~B() will be invoked (if applicable) and that memory will be correctly removed when b is destroyed, and the lifetime is the same as your first example.

That just leaves your question about memory location. The location will be different. Static variables are generally stored in the program's data segment, whereas anything allocated with new will be stored in the heap.

Sign up to request clarification or add additional context in comments.

1 Comment

As an afterthought, there may also be differences in program behaviour when A or B are too large to fit in the heap or data segment, respectively. If B is too large, then new B ought to throw std::bad_alloc. In the case of A, I'm not sure whether a catchable exception is thrown, or if the program will just seg-fault and die.
0

Adding to the first answer, 2 comments (assuming you want to create a singleton).

  1. There are thread/race issues if 2 threads try to access the static instance overlapping, if the access is the first access (when constructor is run). Nowadays, C++ has compiler/standards support that automatically makes this static singleton initialization thread-safe.
  2. In the heap case, you do not want to create a new instance on the heap every time. Just check for nullptr, and only create instance on heap first time.

EDIT: Here is an SO question where the answer contains relevant ref to standard: Heap/dynamic vs. static memory allocation for C++ singleton class instance

2 Comments

As mentioned in the question, in C++11 both: (1) and (2) you mentioned are guaranteed by the compiler. (1) the compiler guarantees that static local variable initialization are thread safe. (2) the compiler guarantees that static local variable initialization will only be executed once and all subsequent calls to this function will skip re-initialization of the static local variable (hence no new instance will be created every time).
@iBrAaAa ? The question does not mention any guarantees from the standard. The relevant section is 6.7.4, see e.g. stackoverflow.com/questions/15062767/… So, using a function-static variable means you get help from the standard with synchronization..

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.