MochiuWiki : SUSE, EC, PCB
案内
メインページ
最近の更新
おまかせ表示
MediaWiki についてのヘルプ
ツール
リンク元
関連ページの更新状況
特別ページ
ページ情報
We ask for
Donations
検索
個人用ツール
ログイン
Toggle dark mode
名前空間
ページ
議論
表示
閲覧
ソースを閲覧
履歴を表示
C++のデザインパターン - シングルトンのソースを表示
提供: MochiuWiki : SUSE, EC, PCB
←
C++のデザインパターン - シングルトン
あなたには「このページの編集」を行う権限がありません。理由は以下の通りです:
この操作は、次のグループのいずれかに属する利用者のみが実行できます:
管理者
、new-group。
このページのソースの閲覧やコピーができます。
== 概要 == シングルトンパターンは、クラスのインスタンスが1つだけ存在することを保証するデザインパターンである。<br> <br> シングルトンパターンの特徴を以下に示す。<br> * プライベートコンストラクタによる外部からのインスタンス化を防止する。 * 静的メソッドによる唯一のインスタンスへのアクセス提供する。 * マルチスレッド環境での同期処理の必要性 <br> シングルトンパターンの使用場面を以下に示す。<br> * 設定マネージャー * データベース接続管理 * ロギングシステム * ファイルシステム <br> しかし、グローバル状態を作り出すため単体テストの難しさやコードの結合度が高くなる等の課題もある。<br> そのため、使用は慎重に検討する必要がある。<br> <br> 実装方法には、ポインタベース、参照ベース、C++11以降では静的局所変数を利用した方法等がある。<br> <br> マルチスレッド対応が必要な場合は、double-checked lockingパターンや静的局所変数の初期化の特性を利用した実装 (C++11以降) も可能である。<br> <br><br> == ポインタベースのシングルトンクラス == 以下の例では、コンストラクタは<code>private</code>で隠蔽して、<code>new</code>の代わりにSingleton::getInstanceメソッドでインスタンスを取得する。<br> privateメンバ変数static Singleton* instanceで自身のインスタンスのポインタを保持している。<br> <br> クラス外部で、Singleton* Singleton::instance = 0;により、自身のインスタンスのポインタを初期化している。<br> <syntaxhighlight lang="c++"> // Singleton.h #ifndef SINGLETON_H #define SINGLETON_H class Singleton { private: static Singleton* m_Instance; // インスタンスのポインタ int m_Data = 1; // シングルトンのインスタンス生成にはgetInstanceメソッドを使用するため、コンストラクタを隠蔽する Singleton() { std::cout << "Singleton instance created" << std::endl; } Singleton(const Singleton&) = delete; // コピーコンストラクタを禁止 Singleton& operator=(const Singleton&) = delete; // 代入演算子を禁止 public: ~Singleton() { if (instance != nullptr) { delete instance; instance = nullptr; } } // インスタンスを取得するメソッド static Singleton* getInstance() { // インスタンスが存在しない場合は生成する if(m_Instance == NULL) { m_Instance = new Singleton(); } return m_Instance; } int getData() { return Singleton::getInstance()->m_Data; } void setData(int data) { Singleton::getInstance()->m_Data = data; } }; // インスタンスのポインタを初期化 Singleton *Singleton::m_Instance = nullptr; #endif </syntaxhighlight> <br> 上記のクラスの使用例を、以下に示す。<br> <syntaxhighlight lang="c++"> #include <iostream> #include "Singleton.h" int main(int argc, char* argv[]) { // インスタンスAを生成 Singleton* InstanceA = Singleton::getInstance(); std::cout << "インスタンス1のアドレス: " << InstanceA << std::endl; // 別のインスタンスBを生成 Singleton* InstanceB = Singleton::getInstance(); std::cout << "インスタンス2のアドレス: " << InstanceB << std::endl; // 各インスタンスのメソッドを呼び出す std::cout << "インスタンスAのdata: " << InstanceA->getData() << std::endl; std::cout << "インスタンスBのdata: " << InstanceB->getData() << std::endl; // インスタンスAの保持データを更新する std::cout << "インスタンスAのメンバ変数を10に更新" << std::endl; inst1->setData(10); // 各インスタンスのメソッドを呼び出す std::cout << "インスタンスAのdata: " << inst1->getData() << std::endl; std::cout << "インスタンスBのdata: " << inst2->getData() << std::endl; return 0; } </syntaxhighlight> <br> # 出力例 インスタンスAのアドレス: 0x9045kd9s インスタンスBのアドレス: 0x9045kd9s インスタンスAのdata: 1 インスタンスBのdata: 1 インスタンスAのメンバ変数を10に更新 インスタンスAのdata: 10 インスタンスBのdata: 10 <br><br> == 参照ベースのシングルトンクラス == 参照ベースのシングルトンクラスは、静的局所変数方式とポインタベース方式の中間的なアプローチである。<br> <br> メモリ管理の注意が必要となり、明示的なデストラクタの実装やスマートポインタの使用すべき場合がある。<br> <br> <syntaxhighlight lang="c++"> class Singleton { private: Singleton() = default; static Singleton* createInstance() { return new Singleton(); } public: Singleton(const Singleton&) = delete; Singleton& operator=(const Singleton&) = delete; static Singleton& getInstance() { static Singleton& instance(*createInstance()); return instance; } }; </syntaxhighlight> <br><br> == 静的局所変数を使用したシングルトンクラス (C++11以降) == 静的局所変数を使用したシングルトンクラスは、以下に示すメリットがある。<br> * スレッドセーフ (C++11規格で保証) * メモリリーク防止 * nullポインタチェックが不要 * デストラクタの明示的実装が不要 * 遅延初期化 (lazy initialization) の実現 * より安全で簡潔な実装 <br> <syntaxhighlight lang="c++"> class Singleton { private: Singleton() = default; // プライベートコンストラクタ (外部からのインスタンス化を防止) public: Singleton(const Singleton&) = delete; // コピーコンストラクタを削除 (シングルトンの複製を防止) Singleton& operator=(const Singleton&) = delete; // 代入演算子を削除 (シングルトンの代入を防止) // C++11以降では、静的局所変数の初期化はスレッドセーフであることが保証されている static Singleton& getInstance() { static Singleton instance; // マルチスレッド環境でも安全 return instance; } // ビジネスロジックメソッド void sampleMethod() { // ...略 } }; </syntaxhighlight> <br> <syntaxhighlight lang="c++"> // 使用例 #include <iostream> int main() { // インスタンスの取得 Singleton& instance1 = Singleton::getInstance(); Singleton& instance2 = Singleton::getInstance(); // 同じインスタンスであることを確認 if (&instance1 == &instance2) { std::cout << "同じインスタンスです" << std::endl; } // ビジネスロジックの実行 instance1.sampleMethod(); return 0; } </syntaxhighlight> <br><br> == double-checked lockingパターンのシングルトンクラス (マルチスレッド対応) == double-checked lockingパターンのシングルトンクラスでは、以下に示す特徴がある。<br> * atomicを使用したスレッドセーフな実装 * メモリバリアによる適切な同期 * 最初のチェックでロックを避けることによるパフォーマンス向上 * 2重チェックによる安全性確保 <br> <u>※注意</u><br> <u>ただし、この実装は複雑で微妙なバグが発生しやすいため、可能であればC++11以降の静的局所変数による実装を推奨する。</u><br> <br> <syntaxhighlight lang="c++"> #include <mutex> // mutex機能とlock_guardを使用するために必要 #include <atomic> // アトミック操作とメモリオーダーを使用するために必要 #include <memory> // スマートポインタを使用する場合に必要 class Singleton { private: // シングルトンインスタンスへのアクセスを同期するためのミューテックス static std::mutex mutex_; // シングルトンインスタンスへのアトミックポインタ // アトミック操作により、マルチスレッド環境での安全性を確保 static std::atomic<Singleton*> instance_; // プライベートコンストラクタ (外部からのインスタンス化を防止) Singleton() = default; public: // コピーコンストラクタを削除 (シングルトンの複製を防止) Singleton(const Singleton&) = delete; // 代入演算子を削除 (シングルトンの代入を防止) Singleton& operator=(const Singleton&) = delete; // シングルトンインスタンスを取得するスレッドセーフな関数 static Singleton* getInstance() { // 最初の確認 : ロック無しでインスタンスの存在を確認 Singleton* tmp = instance_.load(std::memory_order_relaxed); // メモリバリア : 他のスレッドの変更を確実に認識 std::atomic_thread_fence(std::memory_order_acquire); if (tmp == nullptr) { // ロックを取得して2重チェック std::lock_guard<std::mutex> lock(mutex_); tmp = instance_.load(std::memory_order_relaxed); // 2重チェック : 他のスレッドがインスタンスを生成していないことを確認 if (tmp == nullptr) { // 新しいインスタンスを生成 tmp = new Singleton; // メモリバリア : インスタンスの作成を他のスレッドに確実に通知 std::atomic_thread_fence(std::memory_order_release); // 生成したインスタンスを保存 instance_.store(tmp, std::memory_order_relaxed); } } return tmp; } }; // 静的メンバ変数の初期化 std::mutex Singleton::mutex_; std::atomic<Singleton*> Singleton::instance_{nullptr}; </syntaxhighlight> <br><br> __FORCETOC__ [[カテゴリ:C++]]
C++のデザインパターン - シングルトン
に戻る。
案内
メインページ
最近の更新
おまかせ表示
MediaWiki についてのヘルプ
ツール
リンク元
関連ページの更新状況
特別ページ
ページ情報
We ask for
Donations
Collapse