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?

Community
  • 1
  • 1
FaceBro
  • 787
  • 2
  • 13
  • 29
  • 1
    The object is not copied at all, because `instance()` returns a reference and the class itself disallows copying via `Singleton(Singleton const&) = delete;`. – Christian Hackl Feb 25 '17 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. – Kerrek SB Feb 25 '17 at 14:38
  • 1
    I would suggest someone to learn more about linkage before comment about this question – FaceBro Feb 25 '17 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. – Christian Hackl Feb 25 '17 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. – FaceBro Feb 26 '17 at 00:11

3 Answers3

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.

Horstling
  • 2,131
  • 12
  • 14
  • 2
    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. – Kerrek SB Feb 25 '17 at 14:40
  • @KerrekSB Not if foo() is a member function though. – Horstling Feb 25 '17 at 14:43
  • 1
    This is exactly the answer I am looking for. It is also well discussed here http://stackoverflow.com/questions/185624/static-variables-in-an-inlined-functio. Bravo – FaceBro Feb 25 '17 at 14:46
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.

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
  • 1
    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 Feb 25 '17 at 14:55
  • 2
    @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. – Kerrek SB Feb 25 '17 at 14:56
  • 1
    That matches my assumption, Thanks – FaceBro Feb 25 '17 at 15:00
-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 :-) ).

Serge Ballesta
  • 143,923
  • 11
  • 122
  • 252
  • 1
    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. – FaceBro Feb 26 '17 at 00:13