标签云

微信群

扫码加入我们

WeChat QR Code

Recently I've bumped into a realization/implementation of the Singleton design pattern for C++. It has looked like this (I have adopted it from the real life example):// a lot of methods are omitted hereclass Singleton{ public: static Singleton* getInstance( ); ~Singleton( ); private: Singleton( ); static Singleton* instance;};From this declaration I can deduce that the instance field is initiated on the heap. That means there is a memory allocation. What is completely unclear for me is when exactly the memory is going to be deallocated? Or is there a bug and memory leak? It seems like there is a problem in the implementation.My main question is, how do I implement it in the right way?


See also: stackoverflow.com/questions/211237/… and stackoverflow.com/questions/270947/…and stackoverflow.com/questions/246564/… and stackoverflow.com/questions/449436/… and stackoverflow.com/questions/335369/…

2019年05月23日45分52秒

You'll find a great discussion of how to implement a singleton, along with thread-safety in C++ in this paper.aristeia.com/Papers/DDJ%5FJul%5FAug%5F2004%5Frevised.pdf

2019年05月23日45分52秒

sbi - Only a Sith deals in absolutes. Can the vast majority of problems be solved without Singletons? Absolutely. Do Singletons cause problems of their own?Yes. However, I can't honestly say that they're bad, since design is all about considering the tradeoffs and understanding the nuances of your approach.

2019年05月23日45分52秒

derekerdmann: I didn't say you never need a global variable (and when you need one, a Singleton sometimes is better). What I said is that they should be used as little as possible. Glorifying Singleton as a valuable design pattern gives the impression it's good to use it, rather than that it is a hack, making code hard to understand, hard to maintain, and hard to test. This is why I posted my comment. None of what you said so far contradicted this.

2019年05月24日45分52秒

sbi: What you said was "Don't use them." Not the much more reasonable "they should be used as little as possible" you later changed to - surely you see the difference.

2019年05月23日45分52秒

Good answer. But should note that this is not thread-safe stackoverflow.com/questions/1661529/…

2019年05月24日45分52秒

Varuna: In C++11 this is now thread-safe.

2019年05月24日45分52秒

zourtney: Many people don't realize what you just did :)

2019年05月24日45分52秒

MaximYegorushkin: When this is destroyed is very well defined (there is no ambiguity). See: stackoverflow.com/questions/246564/…

2019年05月23日45分52秒

What irks me most though is the run-time check of the hidden boolean in getInstance() That is an assumption on implementation technique. There need be no assumptions about it being alive. see stackoverflow.com/a/335746/14065 You can force a situation so that it is always alive (less overhead than Schwarz counter). Global variables have more issues with initialization order (across compilation units) as you not force an order. The advantage of this model is1) lazy initialization. 2) Ability to enforce an order (Schwarz helps but is uglier). Yep get_instance() is much uglier.

2019年05月24日45分52秒

if delete is never explicitly called on the static Singleton* instance, wouldn't this still technically be considered a memory leak?

2019年05月24日45分52秒

It's not a memory leak anymore than a simple declaration of a global variable.

2019年05月23日45分52秒

To set something straight... "memory leak" concerns vis-a-vis singletons are completely irrelevent. If you have stateful resources in which deconstruction order matters, singletons can be dangerous; but all of the memory is cleanly regained by the operating system on program termination... nullifying this totally academic point in 99.9% of cases.If you want to argue the grammar back and forth of what is and is not a "memory leak", that's fine, but realize that it's a distraction from actual design decisions.

2019年05月24日45分52秒

jkerian: Memory leaks and destruction in the C++ context is not really about the memory leaking. Really it is about resource control. If you leak memory the destroctor is not called and thus any resources associated with the object are not correctly released. Memory is just the simple example we use when teaching programming but there are much more complex resources out there.

2019年05月24日45分52秒

Martin I agree with you completely.Even if the only resource is memory, you will still get into trouble trying to find REAL leaks in your program if you have to wade through a list of leaks, filtering out ones that "don't matter."It is better to clean these all up so any tool that reports leaks only reports things that ARE a problem.

2019年05月24日45分52秒

In some instances, this lazy initialization is not the ideal pattern to follow. One example is if the constructor of the singleton allocates memory from the heap and you wish that allocation to be predictable, for instance in an embedded system or other tightly controlled environment.I prefer, when the Singleton pattern is the best pattern to use, to create the instance as a static member of the class.

2019年05月24日45分52秒

For many larger programs, especially those with dynamic libraries. Any global or static object that's none primitive can lead to segfaults/crashes upon program exit on many platforms due to order of destruction issues upon libraries unloading. This is one of the reasons many coding conventions (including Google's) ban the use of non-trivial static and global objects.

2019年05月23日45分52秒

It seems that the static instance in such implementation has internal linkage, and will have unique and independent copies in different translation unit, which will cause confusing and wrong behavior.But I saw many such implementation, am I missing something?

2019年05月24日45分52秒

Currently under gcc it is thread safe (and has been for a while).

2019年05月24日45分52秒

The problem with this design is that if used across multiple libraries. Each library has is own copy of the singleton that that library uses. So it is no longer a singleton.

2019年05月23日45分52秒

Look like you've tried to use it in the wrong way.

2019年05月23日45分52秒

If you are referring to the currently accepted answer you first statement is wrong. The destructor is not called until all static storage duration objects are destroyed.

2019年05月24日45分52秒

Deprecated in c++11. unique_ptr is recommended instead. cplusplus.com/reference/memory/auto_ptr cplusplus.com/reference/memory/unique_ptr

2019年05月24日45分52秒

This isn't thread safe. Better to make m_s a local static of getInstance()and initialize it immediately without a test.

2019年05月24日45分52秒

you can deduce, since you can see that instance variable is a pointer to the class instance.

2019年05月23日45分52秒

There is no need to dynamically allocate the singleton. In fact this is a bad idea as there is not way to automatically de-allocate using the above design. Let it fall out of scope is does not call destructors and is just lazy.

2019年05月24日45分52秒

You can automatically deallocate using the atexit function. That's what we do (not saying it's a good idea)

2019年05月23日45分52秒

Unfortunately not. This has been discussed in great depth by some of the best C++ developers out there. Double checked locking is broken in C++03.

2019年05月24日45分52秒

Why. That seems complex. And the destructor is never called. Also you need to fix the expression for calculating size currently it will work on average 25% of the time (try the situation where sizeof(singelton) == 3. Then your above expression results in 0 sized array.

2019年05月23日45分52秒