1

C++ Singleton design pattern I come across this question and learned that there are two ways to implement the singleton pattern in c++.

1) allocate the single instance in heap and return it in the instance() call

2) return a static instance in the instance() call, this is also known as the lazy initialization implementation.

But I think the second, that is the lazy initialization implementation, is wrong due to following reasons. Static object returned from the instance() call has internal linkage and will have unique copies in different translation unit. So if user modifies the singleton, it will not be reflected in any other translation unit.

But there are many statement that the second implementation is correct, am I missing something?

5
  • 1
    The object is not copied at all, because instance() returns a reference and the class itself disallows copying via Singleton(Singleton const&) = delete;. Commented Feb 25, 2017 at 14:38
  • 1
    The real difference between dynamic and static storage for the singleton object is destruction. The dynamically stored object is never destroyed, the statically stored one is destroyed at some (unspecified) point during program exit, which some poorly conceived programs may have trouble with. Commented Feb 25, 2017 at 14:38
  • 1
    I would suggest someone to learn more about linkage before comment about this question Commented Feb 25, 2017 at 14:49
  • @FaceBro: Since it was you who had a misconception about linkage, it comes across as very strange for you to tell people to "learn more about" it. Commented Feb 25, 2017 at 15:11
  • 1
    @ChristianHackl It's true that I have misconception and that's why I am asking question to sort it out.Your comment of return reference and deleted copy constructor does not have any point here. Compiler will generate unique copies in each translation unit for objects with internal linkage, regardless of whether the type support copy constructor or not. The deleted copy constructor is intended only to prevent multi copies within one translation unit. Commented Feb 26, 2017 at 0:11

3 Answers 3

5

In the context of a method, the static keyword is not about linkage. It just affects the "storage class" of the defined variable. And for static local variables the standard explicitly states:

9.3.6 A static local variable in a member function always refers to the same object, whether or not the member function is inline.

So it doesn't matter at all whether you put the code in a header or cpp file.

Note that for free / non-member function it does indeed depend on the linkage of the function, as KerrekSB pointed out.

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

3 Comments

That may be a bit misleading. If you have a free function in a header, static int foo() { static int n; return ++n; }, then every translation unit that includes that header has its own, separate counter. Class member functions are somewhat different.
@KerrekSB Not if foo() is a member function though.
This is exactly the answer I am looking for. It is also well discussed here stackoverflow.com/questions/185624/…. Bravo
2

The linkage of the name of implementation object does not matter. What matters is the linkage of the name of the function you use to access the object, and that name has, of course, external linkage:

thing.h:

Thing & TheThing();   // external linkage

thing.cpp:

#include "thing.h"

Thing & TheThing() { static Thing impl; return impl; }

Every use of the name TheThing in the program refers to the same entity, namely the function defined (uniquely) in thing.cpp.

Remember, linkage is a property of names, not of objects.

3 Comments

Good to know, and well explained. One more question though, I think static function for some class will not cause many copies of the instance? because that is the standard way to implement the second form.
@FaceBro: Static class member functions have external linkage. You need to be very careful with the term "static" in C++, it has about 15 different meanings.
That matches my assumption, Thanks
-1

You are wrong, because the singleton is defined in one single translation unit, the one that contains the definition of the function that returns it. That means that all translation units that wants to use the singleton ask it to the single one that actually defines it, and in the end all use the same object (as expected for a singleton pattern :-) ).

1 Comment

Your answer does have valid point about the external linkage of the enclosing function, but you failed to mention one more important point that the local static variable has NO linkage. Without no linkage point, it makes no sense.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.