Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Singleton Pattern Implementation in C++

Tech Jul 7 2

Singleton Pattern Fundamentals

The Singleton pattern ensures a class has only one global instance while providing controlled access to it. This pattern is suitable for scenarios requiring centralized management of shared resources or global configuration settings.

Lazy Initialization Approach

class Logger {
public:
    static Logger* getShared() {
        if (shared_logger == nullptr) {
            shared_logger = new Logger();
        }
        return shared_logger;
    }
private:
    Logger() = default;
    ~Logger() = default;
    static Logger* shared_logger;
};

class Settings {
public:
    static Settings& obtain() {
        static Settings config;
        return config;
    }
private:
    Settings() = default;
    ~Settings() {}
};

These implementations restrict instantiation through private constructors. The first example uses pointer-based delayed initialization, while the second leverages C++11 static local variables for automatic singleton management.

Eager Initialization Method

// Configuration.h
class Configuration {
public:
    static Configuration& fetch() {
        return global_config;
    }
private:
    Configuration() = default;
    ~Configuration() {}
    static Configuration global_config;
};

// Configuration.cpp
Configuration Configuration::global_config;

Eager initialization creates the instance during static initialization, eliminating runtime instantiation overhead and thread-safety concerns.

Thread Safety Considerations

// C++98 Thread-safe Implementation
class DatabasePool {
public:
    static DatabasePool* access() {
        if (db_instance == nullptr) {
            std::lock_guard<std::mutex> guard(pool_mutex);
            if (db_instance == nullptr) {
                db_instance = new DatabasePool();
            }
        }
        return db_instance;
    }
private:
    static DatabasePool* db_instance;
    static std::mutex pool_mutex;
};

// C++11 Thread-safe Implementation
class CacheManager {
public:
    static CacheManager& retrieve() {
        std::call_once(init_flag, [] {
            cache_instance.reset(new CacheManager);
        });
        return *cache_instance;
    }
private:
    static std::unique_ptr<CacheManager> cache_instance;
    static std::once_flag init_flag;
};

These implementations address concurrnet access issues. The C++98 version uses double-checked locking, while the C++11 approach employs std::call_once for initialization safety.

Pattern Comparison

Lazy initialization creates instances on first access, conserving memory but requiring thread synchronization. Eager initialization allocates resources upfront, simplifying implementation but potentially wasting memory.

Practical Applications

  • Resource management: Centralized handling of database connections or thread pools
  • Configuration control: Global access to application settings
  • System services: Unified logging mechanisms accessible throughout an application

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

SBUS Signal Analysis and Communication Implementation Using STM32 with Fus Remote Controller

Overview In a recent project, I utilized the SBUS protocol with the Fus remote controller to control a vehicle's basic operations, including movement, lights, and mode switching. This article is aimed...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.