C++での実装例
出典: フリー百科事典『ウィキペディア(Wikipedia)』 (2021/06/11 16:01 UTC 版)
「Singleton パターン」の記事における「C++での実装例」の解説
C++ではクラスのコンストラクタ、コピーコンストラクタとコピー代入演算子を private にすることで唯一となる。さらにデストラクタを private にすることで派生クラスのスタック上への作成を禁止できる。 静的ローカル変数を利用した実装例を示す。 class Singleton {private: Singleton() {} // コンストラクタを private に置く。 Singleton(const Singleton&); // コピーコンストラクタも private に置き、定義しない。 Singleton& operator=(const Singleton&); // コピー代入演算子も private に置き、定義しない。 ~Singleton() {} // デストラクタを private に置く。public: static Singleton& getInstance() { static Singleton inst; // private なコンストラクタを呼び出す。 return inst; } const char* getString() const { return "Hello world!"; }};// 利用例。int main() { std::cout << Singleton::getInstance().getString() << std::endl; return 0;} 静的ローカル変数を利用して実装した場合、シングルトンインスタンスを削除するタイミングを明示的に制御できないことに注意が必要となる。また、インスタンスが生成されるのは最初にgetInstance()関数を呼び出したタイミングとなるが、C++11よりも前の規格では静的ローカル変数の初期化はスレッドセーフ性が保証されないため、複数のスレッドから同時に初回アクセスが発生した場合、未定義動作を引き起こす。静的ローカル変数ではなく、ポインタ型の静的メンバー変数を利用して実装する場合でも、double-checked lockingなどの技法によるスレッドセーフ化が必要となる。 なお、C++11規格では、コンパイラが生成する関数へのdefault/delete指定により、コンストラクタ/デストラクタ以外はprivateに置かなくてもよくなった。また、finalキーワードでクラスを修飾することで、派生クラスの定義を禁止することができる。さらに、静的ローカル変数の初期化は自動的に排他制御され、スレッドセーフとなる。 class Singleton final {private: Singleton() = default; // コンストラクタを private に置く。 ~Singleton() = default; // デストラクタを private に置く。public: Singleton(const Singleton&) = delete; // コピーコンストラクタを delete 指定。 Singleton& operator=(const Singleton&) = delete; // コピー代入演算子も delete 指定。 Singleton(Singleton&&) = delete; // ムーブコンストラクタを delete 指定。 Singleton& operator=(Singleton&&) = delete; // ムーブ代入演算子も delete 指定。...};
※この「C++での実装例」の解説は、「Singleton パターン」の解説の一部です。
「C++での実装例」を含む「Singleton パターン」の記事については、「Singleton パターン」の概要を参照ください。
- C での実装例のページへのリンク