C++単体モード学習下書き


モノマーモードとは、クラスが最初から最後までインスタンスが1つしかないことを保証することであり、モノマーを実現するには以下の点を保証する必要があります.
  • 構造関数はPrivateまたはProtected
  • である.
  • 構造関数は、PrivateまたはProtected(厳密な説明はない)
  • であるべきである.
  • コピーコンストラクション関数および付与オペレータoperator=PrivateまたはProtectedである必要があります.ただし、
  • は、実装しない(実装しない場合によって異なります)と宣言します.
    C++スレッドセキュリティの一例モード
    1.コピーコンストラクタを含むコンストラクタを定義した場合、コンパイラはデフォルトのデフォルトコンストラクタを提供しませんが、コピーコンストラクタを定義していない限り、オペレータoperator=およびコンストラクタをコピーすると、デフォルトのバージョンが提供されます.コンストラクション関数をPrivateまたはProtectedに設定すれば万事順調だとは思わないでください.実際にはそうではありません.コピーコンストラクション関数(コピーコンストラクション関数+コピーオペレータ)をPrivateまたはProtectedとして宣言する必要があります.
    2.ネット上では、構造関数に対する統一的な意見が見つからず、個人的には、最初から最後まで存在すべきで、一度だけ初期化すべき単体の応用シーンに対して、構造関数をProtectedまたはPrivateに設定する必要があると考えられています.強迫症の友达に対して、すべての資源が優雅に解放されることを望んでいる場合は、次の2つの解決策があります.
    シナリオ1:インタフェースの提供
    #include <stdio.h>
    
    class singleton{
    public:
    	static singleton* instance()
    	{
    		if(NULL == _instance)
    		{
    			_instance = new singleton();
    		}
    		return _instance;
    	}
    	static void destory()
    	{
    		if(NULL != _instance)
    		{
    			delete _instance;
    			_instance = NULL;
    		}
    	}
    private:
    	singleton(){printf("create a object of class singleton.
    ");} singleton(const singleton&); singleton& operator=(const singleton&); ~singleton(){} private: static singleton* _instance; }; singleton* singleton::_instance = NULL;
    このスキームは、ユーザがdestoryインタフェースを正しく使用してプログラムが終了する前に1回だけ呼び出すことができると仮定し、複数回呼び出されても複数のインスタンスが存在しない(単一スレッド)が、インスタンスが一致せず、いくつかの重要な情報が失われる可能性がある.すなわち,これはユーザの自覚性に依存する.しかし,このインタフェースはdeleteを誤用する可能性よりはるかに低い.
    シナリオ2:スマートポインタ
    <pre name="code" class="cpp">#include <stdio.h>
    #include <memory>
    using std::auto_ptr;
    
    class singleton{
    	template <typename T> friend  class auto_ptr;
    	//friend  class auto_ptr<singleton>;  //     
    public:
    	static singleton* instance()
    	{
    		if(NULL == _instance)
    		{
    			_instance = new singleton();
    			auto_ptr<singleton> tmp(_instance);
    			autoDelete = tmp;
    		}
    		return _instance;
    	}
    	
    private:
    	singleton(){printf("create a object of class singleton.
    ");} singleton(const singleton&); singleton& operator=(const singleton&); ~singleton(){printf("delete a object of class singleton.
    ");} private: static singleton* _instance; static auto_ptr<singleton> autoDelete; }; singleton* singleton::_instance = NULL; auto_ptr<singleton> singleton::autoDelete;
     这样的话就可以在最后由智能指针来负责释放实例所占资源了,但是这样所有的auto_ptr智能指针都获得了访问单体私有成员的权利,那么还是有可能多次释放,那么是否还有更好的办法呢,若想要更加安全,见下面的方法: 
      
     

    方案三:内部类

    #include <stdio.h>
    
    class singleton{
    public:
    	static singleton* instance()
    	{
    		if(NULL == _instance)
    		{
    			_instance = new singleton();
    		}
    		return _instance;
    	}
    	
    private:
    	singleton(){printf("create a object of class singleton.
    ");} singleton(const singleton&); singleton& operator=(const singleton&); ~singleton(){printf("delete a object of class singleton.
    ");} private: class destory{ public: ~destory() { delete _instance; _instance = NULL; } }; private: static singleton* _instance; static destory release; }; singleton* singleton::_instance = NULL;
    これにより、プログラムが終了する前にリソースが解放され、外部からリソースを解放するインタフェースが呼び出されず、安全で信頼性が高い.
    シナリオ4:ローカル静的メンバー
    #include <stdio.h>
    
    class singleton{
    public:
    	static singleton* instance()
    	{
    		static singleton _instance;
    		return &_instance;
    	}
    	
    private:
    	singleton(){printf("create a object of class singleton.
    ");} singleton(const singleton&); singleton& operator=(const singleton&); ~singleton(){printf("delete a object of class singleton.
    ");} };
    これにより、リソースの解放の問題を全く心配する必要はありません.