【C++】単例モードにおける構造関数

4260 ワード

最近プロジェクトを書き終えて、ちょうどまとめた時だ.プロジェクトでは多くの単例モードが使用されていますが、ライトカーの熟路のコードを書くと思っていたのに、結果は問題が多く、単例モードはどのように構築されていますか?シングル・インスタンス・モードでスレッドのセキュリティを保証するにはどうすればいいですか?どうやってロックしますか?ロックは単例クラスにカプセル化しますか?この単例クラスは1つのオブジェクトを構築して問題がありますか?ブロックすると後ろに鍵をかける機能が正常に使えませんか?それともロックは単例モードでパッケージされませんか?ロックのオブジェクトを構築するときにstatic???を付ける
テストしないで知らないで、たくさんの問題をテストして解決する必要があります.はい、最初から見ます.
--------------------------------------------------------------------------------------
単例モードを書くにはどうすればいいですか?
「設計モード」という本では、クラスのプライベート静的ポインタ変数を使用してクラスの唯一のインスタンスを指し、共通の静的方法でインスタンスを取得する単一のクラスを定義する優れた実装が示されています.
プロジェクト内の単一モードのコードクリップを任意に探します.
(多くのブログを見て知ったのですが、これはダブルチェックロックでスレッドの安全を保証する怠け者式の単例モードと呼ばれています)
二重チェックロックメカニズムとは、getInstanceメソッドに入るたびに同期が必要になるのではなく、まず同期しないで、メソッドに入った後、インスタンスが存在するかどうかを先にチェックし、存在しなければ次の同期ブロックに入るのが第一のチェックです.同期ブロックに入ると、インスタンスが存在するかどうかを再度確認し、存在しない場合は、同期の場合にインスタンスを作成します.これは2番目のチェックです.これにより、一度だけ同期することができ、同期の場合に複数回の判断を行うのに無駄な時間を短縮することができる.
単一のパターンの特徴をまとめると、
1.コンストラクション関数をプライベート化:外部からコンストラクション関数にアクセスできず、単一オブジェクトの作成を保証
2.プライベートな静的クラスポインタはクラスの唯一のインスタンスを指し、クラス外宣言:staticメンバーはメモリに保存され、静的データメンバーはクラスのメンバーと見なされ、クラスには1部しかありません.静的データ・メンバー定義ではスペースを割り当てるため、クラス宣言では定義できません.クラス外で定義する必要があります
3.アクセスインスタンスを取得するために共通の静的メソッド:静的メソッドはクラスのすべてのサービスです.
class Server
{
public:
	static Server* getServer(string ip,unsigned short port)
	{
		if(NULL == _instance)
		{
            
            pthread_mutex_lock(&mutex);
			if(NULL == _instance)
			{
				_instance = new Server(ip,port);
			}
            pthread_mutex_unlock(&mutex);
		}
		return _instance;
	}

public:
    static pthread_mutex_t mutex;
private:
	Server(string ip,unsigned short port)
	{
	     pthread_mutex_init(&mutex,NULL);
	}
	static Server* _instance;
};
Server* Server::_instance = NULL;

pthread_mutex_t Server::mutex;

 
書き終わったら、一つのnewが一つのdeleteに対応していることを思い出します.
そこで、もちろん関数に構造関数を加えたと思います.以下のようにします.
	~Server()
	{
		delete _instance; 
	}

プログラム実行時、クラッシュ、core dumpが発生しました
では、構造関数とは何か、その役割は何かを分析します.
1、解析関数名はクラス名の前に「~」を付けます.2、構造関数にはパラメータ、戻りタイプ、修飾子がありません.3、1つのクラスに最大1つの解析関数があり、プログラマが解析関数を定義していない場合、システムは自動的に1つの解析関数を追加します.4、構造関数を明示的に呼び出すのではなく、システムによって自動的に呼び出す.△プログラムexit関数を書いたことがありますが、分析を自発的に呼び出して、咳をして、本当に..昔のことは振り返るにたえません...
5.先构造の后析构造、十分な先析构造.....(大学二年生から卒業までの一言...)
構造関数はいつ呼び出されますか?
解析関数は、下の3つの場合に呼び出されます:1.オブジェクトのライフサイクルが終了し、破棄された場合.2.deleteがオブジェクトのポインタを指す場合、またはdeleteがオブジェクトのベースクラスタイプポインタとそのベースクラス架空関数が虚関数である場合.3.オブジェクトiはオブジェクトoのメンバであり、oの構造関数が呼び出されると、オブジェクトiの構造関数も呼び出される
では、問題が見つかりました
~Server()     {         delete _instance;      }
構造関数のdelete_instance;_Instanceはクラスの一意のオブジェクトのポインタであり、
deleteがオブジェクトのポインタを指すときに構造関数を呼び出すと,このコードは~サーバ()を呼び出し,~サーバでdeleteオブジェクトのポインタを呼び出すと無限再帰に陥り,プログラムがクラッシュする.
 
解決方法:
プログラムが終了すると、システムはすべてのグローバル変数を自動的に解析します.実際、システムは、これらの静的メンバーもグローバル変数であるように、すべてのクラスの静的メンバー変数を解析します.この特徴を用いて,このような静的メンバー変数を単一クラスで定義することができ,その唯一の作業は,構造関数で単一クラスのインスタンスを削除することである.次のコードのGarboクラス(Garboはゴミ労働者を意味する):
class Garbo//外部からのアクセスをプライベートで防止するように設定{public:~Garbo()/実際にnewを解析する単一のオブジェクト{if(Server L::_instance!=NULL){                         deleteServerL::_instance;                         ServerL::_instance = NULL;                     }                 }         };
 static Garbo garbo;//静的でプライベートなネストされたクラスオブジェクトで、外部からのアクセスを防止
最終的に、この単一モードのServerクラスは次のようになります.
class Server
{
public:
	static Server* getServer(string ip,unsigned short port)
	{
		if(NULL == _instance)
		{     
            pthread_mutex_lock(&mutex);
			if(NULL == _instance)
			{
				_instance = new Server(ip,port);
			}
            pthread_mutex_unlock(&mutex);
		}
		return _instance;
	}

public:
    static pthread_mutex_t mutex;
private:
    class Garbo //           
    {
     public:
          ~Garbo()//     new     
          {
              if(ServerL::_instance != NULL)
               {
                   deleteServerL::_instance;
                   ServerL::_instance = NULL;
                }
          }
     };
     static Garbo garbo;
private:
	Server(string ip,unsigned short port)
	{
	     pthread_mutex_init(&mutex,NULL);
	}
	static Server* _instance;
};
Server* Server::_instance = NULL;

pthread_mutex_t Server::mutex;