SingletonのC++実装と関連問題
3863 ワード
プログラムを作成する場合、現在のプログラムにobjectが1つしかないことが多い.たとえば、1つのプログラムにはデータベースとの接続が1つしかなく、マウスのobjectが1つしかありません.
最も簡単な方法は、グローバル変数を使用するか、静的変数を使用することです.しかし、これは基本的なObject Oriented Designの原則に違反し、プログラム実行の全体的な構造、可読性、メンテナンスを大幅に低下させる.また,作成したプログラムがメインプログラムではなくdllであれば,グローバル変数の寿命を制御することはさらに困難である.
Design Patternの中で最も簡単で応用が最も広いのはSingletonであり,この問題を解決するために用いられる.以下は単純なSingletonのC++の実装であり,このclassを適用すると現在のプログラムにcopyが1つしかないことを保証できる.
もう1つの実装方法は、次のとおりです.
最初はthread_ではありませんsafe .
私はN日を見てもこの実現がどのようにthread safeなのか気づかなかった.複数の議論を経て、この実装は最初と同じようにthread safeではないことを証明した.2つのプロセスが同時にGetInstanceに入る同時にm_pInstanceはNULLで、constructorが特に時間をかけたときに事故が発生する可能性があります.マルチプロセスのプログラムで使用する場合は、GetInstance関数の開始と終了に「Cretical Section」を付けるとよいでしょう.
私がこの部分を勉強した後、彼が私のプロジェクトに使えないことに気づいた.私のプロジェクトで管理するこのobjectにはいくつかのcopyがあるかもしれないからだ.では、上の概念を少し拡張する必要があります.static Singleton instanceを配列またはvectorに変換します.これにより生成できる数は決定される.ユーザはGetInstanceを複数回使用することでメモリの管理を変更することはありません.もちろんユーザがGetInstance()を使うときは,Getのどのcopyが欲しいかを知り,GetInstance()にパラメータを加えるべきである.ちょっと複雑です.
最も簡単な方法は、グローバル変数を使用するか、静的変数を使用することです.しかし、これは基本的なObject Oriented Designの原則に違反し、プログラム実行の全体的な構造、可読性、メンテナンスを大幅に低下させる.また,作成したプログラムがメインプログラムではなくdllであれば,グローバル変数の寿命を制御することはさらに困難である.
Design Patternの中で最も簡単で応用が最も広いのはSingletonであり,この問題を解決するために用いられる.以下は単純なSingletonのC++の実装であり,このclassを適用すると現在のプログラムにcopyが1つしかないことを保証できる.
Class Singleton {
public
:
static
Singleton
*
GetInstance() {
static
Singleton instance;
return
&
instance; }
protected
: Singleton();
~
Singleton(); }
constructorもdestructorもprotectedなので、このclassを直接生成することはできません.使用時にSingleton::GetInsgtance()をそのまま使えばいいです.Singletonの寿命を心配する必要はありません.もう1つの実装方法は、次のとおりです.
Class Singleton {
public
:
static
Singleton
*
GetInstance() {
if
(
!
m_pInstance) m_pInstance
=
new
Singleton();
return
pinstance; }
private
:
static
Singleton
*
m_pInstance;
protected
: Singleton();
~
Singleton(); }
という書き方の問題は、new後の適切なタイミングでdeleteがこのInstanceを落とす必要があることです.この寿命は制御しにくい.しかし、この実現はthreadだと言う人もいます.safeの.最初はthread_ではありませんsafe .
私はN日を見てもこの実現がどのようにthread safeなのか気づかなかった.複数の議論を経て、この実装は最初と同じようにthread safeではないことを証明した.2つのプロセスが同時にGetInstanceに入る同時にm_pInstanceはNULLで、constructorが特に時間をかけたときに事故が発生する可能性があります.マルチプロセスのプログラムで使用する場合は、GetInstance関数の開始と終了に「Cretical Section」を付けるとよいでしょう.
私がこの部分を勉強した後、彼が私のプロジェクトに使えないことに気づいた.私のプロジェクトで管理するこのobjectにはいくつかのcopyがあるかもしれないからだ.では、上の概念を少し拡張する必要があります.static Singleton instanceを配列またはvectorに変換します.これにより生成できる数は決定される.ユーザはGetInstanceを複数回使用することでメモリの管理を変更することはありません.もちろんユーザがGetInstance()を使うときは,Getのどのcopyが欲しいかを知り,GetInstance()にパラメータを加えるべきである.ちょっと複雑です.