C++:単例モード-餓漢/怠け者

14291 ワード

単一モード:
  • クラスには、システムに1つのインスタンスしかないことを保証し、すべてのプログラムモジュールによって共有されるセキュリティ・ローカル・アクセス・ポイントにアクセスするオブジェクト、すなわち単一のインスタンス・モードしか作成できません.サーバ構成の管理に使用します.

  • コンストラクション関数のプライベート化/コピー防止
    コンストラクション関数の私有化/コピー防止は、怠け者の餓漢を実現するために必要な手段です.もしあなたがすでに理解している場合は、次の部分に直接ジャンプしてください.
  • コンストラクション関数のプライベート化:クラスのコンストラクション関数をプライベート化し、コピーコンストラクションはプライベートを宣言します.スタック上でオブジェクトを生成する他のコピーを防止します.
  • コピー防止:コピーオブジェクトを制限することも考慮されます.制限がないため、コピー時にデフォルトの構造を直接呼び出すことができます.
  • はC 98に基づいて、プライベートクラスでコピー構造が実現しないことを宣言するだけである.
  • C 11:削除関数に基づいて、「関数=delete」はどんな場合でも使用できません.

  • 具体的な例を用いて、それらが具体的にどのように実現されているかを見てみましょう.クラスを設計し、このクラスはスタック上でオブジェクトを作成するしかありません(newで申請するしかありません)
  • .
  • は構造関数を私有化し、他の人は直接外部でオブジェクトを作成することができず、私が規定したスタック上で空間を申請する関数申請をすることができます.スタティックメンバー関数を提供することを使用して、このスタティックメンバー関数の中でスタックオブジェクトの作成を完了し、コピーを防止し、他の人もコピー構造を通じてドリルダウンアクセスを構築することができ、C 89のプライベートクラスに基づいてコピー構造を実現しない方法が友元関数に遭遇した場合、脆弱性が発生することを宣言するだけであることに注意し、ここではC 11の特性-削除関数を使用する.
  • class Heap{
    public:
        static Heap* GetHeap(){
            return new Heap;
        }
    private:
        Heap()
        {}//       ,       ;
        //Heap(const Heap&b);//
        Heap(const Heap&b) = delete//    
    };//C11
    
    int main(){
        Heap*p1 = Heap::GeatHeap();
        return 0;
    }
    

    餓漢モード
  • は、将来使用するかどうかにかかわらず、プログラムを起動するときに唯一のインスタンスオブジェクトを作成します(わあ、私は3日間食べていません.食べ物を見るとすぐに消滅します!)
  • この単一のオブジェクトがマルチスレッドの高い同時環境で頻繁に使用され、性能要件が高い場合、明らかに餓漢モードを使用して資源競争を回避し、応答速度を向上させることがより良い.
  • の利点:簡単;欠点:起動が遅い可能性があります.
  • 要点:1つのインスタンスしか作成できないので、プライベート/コピー防止
  • を構築します.
    class Singleton{
    public:
        static Singleton* GetInstance(){//    ;
            return &_sInstance;
        }
    private:
        Singleton()
        {}
        //   ;
        Singleton(const Singleton&) = delete;
        Singleton& operator=(const Singleton&) = delete;
        static Singleton _sInstance;
    };
    
    Singleton Singleton::_sInstance;//                 ;
    int main(){
        return 0;
    }
    

    怠け者モード
  • このオブジェクトを使用して再作成する必要があります(何を急いで、ポケットに入れてお腹が空いてから食べましょう!)
  • 単一のオブジェクトの构造に时间がかかるか、プラグインのロード、ネットワーク接続の初期化、ファイルの読み取りなど、多くのリソースを占有している场合、オブジェクトの実行时に使用されない可能性がありますが、プログラムの最初から初期化を行うと、プログラムの起動が非常に遅くなります.この場合、怠け者モード(遅延ロード)を使用するとより良いです.
  • の利点:インスタンスを初めて使用するときに作成され、起動時間が短い.欠点:複雑
  • 要点:コピー防止/スレッドセキュリティ(ロック解除)/double check(インスタンス作成後、ロック解除を行わない)効率向上/注意回収
  • class Singleton{
    public:
        static Singleton* GetInstance(){//    ;
            if(nullptr ==_sInstance){//   :       ,          (    ,        ,    ),        ,    ;
                m_mtx.lock();//    ,t1      ,t2    t1     ;          ,      ,      ,     ;
                     if(_sInstance==nullptr){//              ;
                _sInstance=new Singleton;
              }
              m_mtx.unlock();//  ;
           }
           return _sInstance;
        }
         class CGarbo {//             
        public:
            ~CGarbo(){
                if (Singleton::_sInstance)
                    delete Singleton::_sInstance;
            }
        };
    private:
        Singleton()
        {}
        //     ;
        Singleton(const Singleton&) = delete;
        Singleton& operator=(const Singleton&) = delete;
        static CGarbo Garbo;//          ,main     ,         ,                   ;
        static Singleton* _sInstance;//      
        static mutex m_mtx;//    
    };
    
    Singleton* Singleton::_sInstance=nullptr;
    Singleton::CGarbo Singleton::Garbo;//              
    mutex Singleton::m_mtx;
    void func(int n){
        cout<< Singleton::GetInstance() << endl;
    }
    int main(){
        thread t1(func, 10);//      
        thread t2(func, 10);
        t1.join();//   t   t1,t2,   t1,t2    ;
        t2.join();
        cout << Singleton::GetInstance() << endl;
        cout << Singleton::GetInstance() << endl;
    }
    

    ヨヨヨヨヨヨヨヨヨヨヨヨヨヨヨヨヨヨヨヨヨヨヨヨヨヨヨヨヨヨヨヨヨヨヨヨヨヨヨヨヨヨヨヨヨヨヨヨヨヨヨヨヨヨヨヨヨヨヨヨヨヨヨヨヨヨヨヨヨヨヨヨヨヨヨヨヨヨヨヨヨヨ