Discover the elegance of the Singleton design pattern in C++. Learn how to ensure a class has a single instance while providing global access and which is thread-safe. Explore with a concise code example.
The Singleton pattern is a design pattern that ensures a class has only one instance and provides a global point of access to that instance.
- In simple terms, the Singleton design pattern ensures that during the entire program’s execution, there will be only one instance of the singleton class at any point in time.
- You can use the singleton pattern to make any class class singleton as per requirement.
Here’s how you can implement the Singleton pattern in C++:
class Singleton {
public:
static Singleton& getInstance() {
static Singleton instance; // This will be created once and only once
return instance;
}
void doSomething() {
std::cout << "Singleton instance is doing something." << std::endl;
}
private:
Singleton() {} // Private constructor to prevent external instantiation
Singleton(const Singleton&) = delete; // Delete copy constructor
Singleton& operator=(const Singleton&) = delete; // Delete assignment operator
};
int main() {
Singleton& singleton = Singleton::getInstance();
singleton.doSomething();
// Trying to create another instance will result in a compilation error
// Singleton anotherInstance; // Error: 'Singleton::Singleton()' is private within this context
return 0;
}
In this example, the getInstance method returns a reference to the single instance of the Singleton class.
The constructor is private, which prevents external code from creating instances. The Singleton class also deletes the copy constructor and assignment operator to prevent accidental copying of the instance.
Is this singleton design pattern implementation thread safe?
Yes, the provided code is thread-safe due to the use of the static variable for the instance creation. In C++11 and later, the initialization of local static variables inside a function is guaranteed to be thread-safe. This means that the instance will be created only once, even in a multi-threaded environment. Each thread will wait for the initialization to complete before accessing the instance. Therefore, the code snippet above for the Singleton pattern is indeed thread-safe.
IMPORTANT NOTE:
Please note that while the above implementation is thread-safe due to C++11’s guarantee of static variable initialization in a thread-safe manner (static variable initialization is not guaranteed to be thread-safe in older C++ version) , you might need additional synchronization mechanisms if you’re working with older versions of C++ or in a multi-threaded environment.
For older version of C++: You can read this post: Singleton Design Pattern for Pre-C++11 that handle threads and memory.
Want to validate single object with this singleton class?
Use the below code besides the singleton class:
void testSingletonCreation() {
Singleton& instance1 = Singleton::getInstance();
Singleton& instance2 = Singleton::getInstance();
if (&instance1 == &instance2) {
std::cout << "Both instances are the same. Singleton pattern works." << std::endl;
} else {
std::cout << "Instances are different. Singleton pattern failed." << std::endl;
}
}
int main() {
testSingletonCreation();
return 0;
}