Design Patterns in C++
Singleton Pattern
Implement the Singleton pattern in C++ using Meyers' Singleton to guarantee thread safety.
Interview: Meyers' Singleton thread safety guarantees (C++11), deleting copy constructors, and Singleton testing trade-offs.
The Singleton Pattern ensures that a class has only one instance and provides a global point of access to it. In modern C++, the standard way to implement this pattern is Meyers' Singleton, which is thread-safe by default.
Meyers' Singleton
Uses a static local variable inside the instance method. The compiler guarantees its initialization is thread-safe.
Deleted Overloads
Copy constructors and copy assignment operators must be explicitly deleted (= delete).
Lazy Initialization
The singleton instance is created only when the getInstance() function is called for the first time.
Why Meyers' Singleton is Thread-Safe
Starting in C++11, the language standard guarantees that static local variables are initialized in a thread-safe manner:
Standard Guarantee (Section 6.7)
If control enters the declaration of a local static variable concurrently, the executing thread blocks until initialization is complete. This eliminates the need for manual double-checked locking mechanisms.
Code Walkthrough
A thread-safe Singleton database connection pool manager.
#include <iostream> #include <string>class DatabaseConnector { private: // 1. Private constructor to prevent direct instantiation DatabaseConnector() { std::cout << "Database Connection Established.\n"; }
public: // 2. Disable copying and assignment DatabaseConnector(const DatabaseConnector&) = delete; DatabaseConnector& operator=(const DatabaseConnector&) = delete;
// 3. Thread-safe Meyers' Singleton access point static DatabaseConnector& getInstance() { static DatabaseConnector instance; // Initialized thread-safely on first execution return instance; }
void executeQuery(const std::string& query) { std::cout << "Executing: " << query << "\n"; } };
int main() { // Access singleton instance DatabaseConnector::getInstance().executeQuery("SELECT * FROM users"); return 0; }
Interview-Relevant Information
Q: How does Meyers' Singleton guarantee thread-safe initialization?
Answer: C++11 standard rules guarantee that local static variables are initialized thread-safely. The compiler inserts lock guards around the initialization block internally, blocking other threads until the constructor finishes.
Q: Why is Singleton often considered an anti-pattern?
Answer: Singletons introduce global state, make unit testing difficult due to persistent state across tests, and create tight coupling. It is often preferred to manage class lifetimes using Dependency Injection.
Quick Checklist
Did you declare constructors as private? Did you delete the copy constructor and assignment operator? If yes, your Singleton design is safe.
Use Cases
Managing database connection pools or system configuration properties dynamically.
Developing global log managers or application configuration registries.
Common Mistakes
Forgetting to delete copy constructor and assignment operator, allowing duplicates to be created.
Implementing manual double-checked locking using dynamic pointers (which is error-prone and redundant in modern C++).