C++
 Computer >> コンピューター >  >> プログラミング >> C++

C++のシングルトンデザインパターンをわかりやすく解説!実装例とスレッドセーフな書き方


シングルトンパターンとは

シングルトンデザインパターンは、あるクラスのインスタンス生成を1つのオブジェクトだけに制限するソフトウェア設計パターンです。システム全体の動作を1つのオブジェクトで一元管理したい場合に特に有効です。

代表的な使用例として、ファイルへログを出力するロガーが挙げられます。ロガーのインスタンスが複数存在すると、同じファイルへの同時書き込みによる競合やログの分散といった問題が発生する可能性があります。そこでシングルトンクラスを利用すれば、ロガーを確実に1つだけに保つことができます。

基本的な実装例

次のコードは、C++でシングルトンクラスを実装した例です。

#include <iostream>

using namespace std;

class Singleton {
    static Singleton *instance;
    int data;

    // コンストラクタをprivateにして、外部からインスタンスを生成できないようにする
    Singleton() {
        data = 0;
    }

public:
    static Singleton *getInstance() {
        if (!instance)
            instance = new Singleton;
        return instance;
    }

    int getData() {
        return this->data;
    }

    void setData(int data) {
        this->data = data;
    }
};

// 最初にgetInstance()が呼ばれたときに初期化されるよう、ポインタは0で初期化しておく
Singleton *Singleton::instance = 0;

int main() {
    Singleton *s = s->getInstance();
    cout << s->getData() << endl;
    s->setData(100);
    cout << s->getData() << endl;
    return 0;
}

実行結果

このプログラムを実行すると、次の出力が得られます。

0
100

コードのポイント

  • コンストラクタをprivateにすることで、外部から自由にインスタンスを生成することを防止しています。
  • getInstance()は静的メンバ関数として定義され、初回呼び出し時にのみインスタンスを生成し、以降は常に同じインスタンスへのポインタを返します。
  • staticメンバ変数instanceは、クラス外で0(NULL)に初期化しておく必要があります。

注意点:マルチスレッド環境での扱い

上記の実装は、マルチスレッド環境では注意が必要です。複数のスレッドが同時にgetInstance()を呼び出すと、インスタンスが複数生成されてしまう恐れがあります。

C++11以降では、次のようにローカルのstatic変数を利用した「Meyers' Singleton(マイヤーズ・シングルトン)」と呼ばれる手法を使うことで、簡潔かつスレッドセーフに実装できます。

class Singleton {
    int data;

    Singleton() : data(0) {}

public:
    static Singleton& getInstance() {
        static Singleton instance; // 初回呼び出し時に一度だけ生成される
        return instance;
    }

    int getData() { return data; }
    void setData(int d) { data = d; }
};

C++11からは、関数内static変数の初期化がスレッドセーフであることが言語仕様によって保証されているため、新規プロジェクトではこちらの方式が推奨されます。


  1. C++で学ぶコンポジットパターン(複合デザインパターン)の基礎と実装例

    コンポジットパターン(Composite Pattern)は、複数のオブジェクトからなるグループを、あたかも単一のオブジェクトであるかのように扱いたい場面で活用されるデザインパターンです。 このパターンでは、オブジェクトを木構造(ツリー構造)として組み立てることで、「部分」と「全体」の両方の階層を一貫した形で表現できます。オブジェクト群のツリー構造を生成するパターンであるため、GoFデザインパターンの分類では「構造に関するパターン(Structural Patterns)」に属します。 コンポジットパターンの基本概念 コンポジットパターンでは、自分自身と同じ型のオブジェクト群を内部に保持するク

  2. C#でシングルトンパターンを実装する方法を徹底解説!基本の考え方とサンプルコード

    シングルトンパターンとはシングルトンパターンは、GoFデザインパターンの中でも「生成(Creational)」に分類されるパターンのひとつです。このパターンは、特定のクラスのインスタンスがアプリケーション内で必ず1つだけ生成されることを保証したい場合に使用します。生成された唯一のインスタンスが、アプリケーション全体の処理や状態の調整役を担います。設定情報の管理、ログ出力、データベース接続など、複数のインスタンスが存在すると不整合が発生する可能性がある場面でよく活用されます。実装のポイントシングルトンパターンを正しく実装するには、以下のポイントを押さえておく必要があります。すべてのコンストラクタ