Home arrow C++ arrow Page 4 - C++ In Theory: The Singleton Pattern, Part I
C++

C++ In Theory: The Singleton Pattern, Part I


Have you ever wondered how to implement a class with simple logging functionality? J. Nakamura explains how to do it in a way that makes use of the Singleton pattern.

Author Info:
By: J. Nakamura
Rating: 4 stars4 stars4 stars4 stars4 stars / 86
January 18, 2005
TABLE OF CONTENTS:
  1. · C++ In Theory: The Singleton Pattern, Part I
  2. · A Logging Class
  3. · Statics are not Singletons
  4. · The Gamma Singleton
  5. · The Meyers Singleton

print this article
SEARCH DEVARTICLES

C++ In Theory: The Singleton Pattern, Part I - The Gamma Singleton
(Page 4 of 5 )

It is clear that singletons are not very flexible when we have to rely on static variables and functions. But I have digressed a little, so let's have a look at how the Log class would be implemented as a singleton in "Design Patterns" [Gamma].

class Log {

public:
  static Log* Instance() {
    if (!m_pInstance)
      m_pInstance = new Log;
    return m_pInstance;
}
  void Write(char const *logline);
  bool SaveTo(char const *filename);
private:
  Log();        // ctor is hidden
  Log(Log const&);    // copy ctor is hidden

  static Log* m_pInstance;
  static std::list<std::string> m_data;
};

// in log.cpp we have to add
Log* Log::m_pInstance = NULL;

The constructor and copy constructor are hidden because they are made private, so no user has access to them except for the class itself. The only way to instantiate a Log is by calling Instance() which checks whether or not this class has already been instantiated. This seems like the perfect way to restrict access to our class, and we are sure that only one is ever created during the lifetime of our application!

“Seems?” I hear you think. If you look closely, you will notice that m_pInstance is never destructed. Depending on the definition you use for memory leakage, this class is actually leaking memory.

Some consider a memory leak to be an accumulation of data, of which you lose the references (and thus the ability to free them) during runtime. In this case m_pInstance is holding on to the memory right up to the end of the application, so does not have to be considered a memory leak. Since most operating systems free the memory a process has been using when it terminates, m_pInstance can be considered not to be leaking.

You should not depend on the operating system to clean up the memory you have allocated, especially not when your code has to be platform independent. There is at least one OS out there that doesn’t free the memory left allocated by a terminated process (I don't remember which one…most probably it is the OS/400) and if your singleton opened a file, socket or other system resources, these may remain locked after the process has closed and you will have created a resource leak.

Maybe we should have coded our Log singleton this way:

class Log {
public:
  static Log* Instance() {
    return &m_pInstance;
}
  void Write(char const *logline);
  bool SaveTo(char const *filename);
private:
  Log();        // ctor is hidden
  Log(Log const&);    // copy ctor is hidden

  static Log m_pInstance;
  static std::list<std::string> m_data;
};

// in log.cpp we have to add
Log Log::m_pInstance;

This solution loses an important benefit that our previous singleton did have: dynamic initialization. It is useful for your application to only create the singleton when it is needed/called upon. With our polymorphic example, every class would be instantiated and we would have to instantiate all forms of logging (even when this might not be possible!), while only using one of them!

Static initialization remains a problem as well. There is no guaranteed sequence in which statics are created and destroyed…which will cause problems for our logging class, but we will take a more detailed look at this later on.


blog comments powered by Disqus
C++ ARTICLES

- Intel Threading Building Blocks
- Threading Building Blocks with C++
- Video Memory Programming in Text Mode
- More Tricks to Gain Speed in Programming Con...
- Easy and Efficient Programming for Contests
- Preparing For Programming Contests
- Programming Contests: Why Bother?
- Polymorphism in C++
- Overview of Virtual Functions
- Inheritance in C++
- Extending the Basic Streams in C++
- Using Stringstreams in C++
- Custom Stream Manipulation in C++
- General Stream Manipulation in C++
- Serialize Your Class into Streams in C++

Watch our Tech Videos 
Dev Articles Forums 
 RSS  Articles
 RSS  Forums
 RSS  All Feeds
Write For Us 
Weekly Newsletter
 
Developer Updates  
Free Website Content 
Contact Us 
Site Map 
Privacy Policy 
Support 

Developer Shed Affiliates

 




© 2003-2017 by Developer Shed. All rights reserved. DS Cluster - Follow our Sitemap
Popular Web Development Topics
All Web Development Tutorials