| by Arround The Web | No comments

How to Create a Singleton in C++

In C++, a singleton is a design principle that ensures the presence of a solitary instance of the class throughout the program and provides a global access point to that particular instance.

The singleton pattern is commonly used when you need to have a single, shared resource that should be accessed globally such as a database connection, a logger, or a configuration manager. By enforcing a single instance, it allows multiple parts of the program to access and modify the same object, promoting data consistency and reducing the need for global variables. Singleton can be employed as an object cache where the frequently used or expensive-to-create objects are stored and reused throughout the application. This approach helps improve the performance by avoiding redundant object creation and initialization.

In this article, we will explain the creation of a singleton and demonstrate an example of stylizing a singleton in a C++ program.

Example 1: Creating a Simple Singleton with Eager Initialization

A simple singleton with early initialization is a design pattern that ensures that only one instance of a class is created, and it is created eagerly during static initialization.

We will demonstrate the basic code snippet for the creation of a simple singleton with eager initialization. Let’s start with the program:

#include <iostream>

class Singleton {
private:
  static Singleton* instance;
  Singleton() {}
public:
  static Singleton* getInstance() {
    return instance;
  }
};

Singleton* Singleton::instance = new Singleton();

int main() {

  Singleton* singletonInstance1 = Singleton::getInstance();

  Singleton* singletonInstance2 = Singleton::getInstance();

  std::cout << "singletonletonInstance1: " << singletonInstance1 << std::endl;

  std::cout << "singletonletonInstance2: " << singletonInstance2 << std::endl;

  return 0;

}

The code includes the <iostream> header which provides the functionality to work with input and output streams such as “std::cout”.

After including the header file, we define the “Singleton” class which represents the singleton pattern implementation. It has a private constructor and a private static member variable named “instance”.

Then, the getInstance() function is implemented as a public static member function of the “Singleton” class. It returns the instance of the singleton that is stored in the static member variable instance. The static member variable instance is defined and initialized outside the class with “Singleton* Singleton::instance = new Singleton();”. This line initializes the instance of the “Singleton” class eagerly during static initialization.

In the main() function, we declare two pointers, “singletonInstance1” and “singletonInstance2”, and assign the value that is returned by calling the Singleton::getInstance(). Since the instance is eagerly initialized, both pointers point to the same instance. The “std::cout” statements print the memory addresses of “singletonInstance1” and “singletonInstance2” to the console using the “<<” operator and “std::endl”.

The code ends with a “return 0” which indicates a successful program execution.

When you run this code, the output is something like this:

The output displays the memory addresses of “singletonInstance1” and “singletonInstance2”. Since both pointers are assigned with the same instance that are obtained from Singleton::getInstance(), they have the same memory address. This demonstrates how the singleton pattern guarantees that there is a single instance of the class and that the future calls to getInstance() always result in the same instance.

Example 2: Singleton Pattern Implementation with Lazy Initialization

This demonstration explains the singleton pattern implementation with lazy initialization and shows its usage in the main() function. The step-by-step explanation of the code snippet is provided after this program:

#include<iostream>

class Singleton {

private:

  static Singleton* instance;

  Singleton() {

    std::cout << "Singleton instance created." << std::endl;

  }

public:

  static Singleton* getInstance() {

   if (instance == nullptr) {

     instance = new Singleton();

   }

   return instance;

   }

   void showMessage() {

     std::cout << "Hello from Singleton!" << std::endl;

   }

   ~Singleton() {

   std::cout << "Singleton instance destroyed." << std::endl;

   }

   };

   Singleton* Singleton::instance = nullptr;

   int main() {

      Singleton* singletonInstance1 = Singleton::getInstance();

      singletonInstance1->showMessage();

      Singleton* singletonInstance2 = Singleton::getInstance();

      singletonInstance2->showMessage();

      return 0;

}

The program starts by adding the <iostream> header file to carry out the input/output tasks. Then, we declare and define a “Singleton” class. The sole instance of the class is kept within the private static member variable named “instance”.

Whenever the “Singleton” class’s constructor is called, it generates an instance of the “Singleton” class. It outputs the “Singleton instance created” message to the console using the “std::cout << … << std::endl;”. The constructor does not have any parameters as it is a default constructor. It is defined as Singleton() without any arguments. We declare it as private which means that it can only be invoked from inside the class. This prevents a direct instantiation of the “Singleton” class and ensures that the only way to obtain an instance is through the getInstance() function.

The “Singleton” class’s getInstance() method is declared as a public static member function. It is in the role of establishing and granting accessibility to the singleton instance. Inside the getInstance(), it checks if the instance is “nullptr”. If it is, signifying that the instance is not already present, it uses the private constructor to instantiate a new object of the “Singleton” class.

The showMessage() function is a simple member function that displays the “Hello from Singleton!” message. The destructor of singleton is defined. It is called implicitly when the program terminates and prints the “Singleton instance destroyed.” message which indicates that the singleton instance is destroyed. The static member variable instance is initially defined as “nullptr”.

The int main() starts the definition of the main() function. Then, the “Singleton* singletonInstance1 = Singleton::getInstance();” calls the getInstance() function of the “Singleton” class to obtain a pointer to the singleton instance. It assigns this pointer to the “singletonInstance1” variable.

After that, the “singletonInstance1->showMessage();” uses the arrow operator (->) to call the showMessage() function on the “singletonInstance1” pointer. This function displays the message that is specified in it to the console. Afterward, the “Singleton* singletonInstance2 = Singleton::getInstance();” calls the getInstance() function again, obtaining another pointer to the singleton instance. This time, it assigns the pointer to the “singletonInstance2” variable. The “singletonInstance2->showMessage();” calls the showMessage() function on the “singletonInstance2” pointer. This function displays the “Hello from Singleton!” message again to the console.

Lastly, “return 0;” signifies the end of the main() function, and the program returns the value of 0 which signifies a successful program execution.

Here is the output of the previously-explained code snippet:

This result confirms that the “Singleton” class assures the creation of just one instance and that further calls to the getInstance() function reliably yield the same instance.

Conclusion

Creating a singleton in C++ is a very useful concept. In this post, we initially covered the introduction section of singleton. Furthermore, two examples are produced to implement the singleton in C++. The first illustration shows the implementation of the eager singleton initialization. Whereas the lazy initialization implementation of the singleton pattern is provided in the second example of this article. Moreover, the snapshots of the produced output are also displayed for the corresponding programs.

Share Button

Source: linuxhint.com

Leave a Reply