2016-12-29 7 views
3

私はサプライヤのアプリケーションからいくつかの新しいコードを使って作業しています。そのライブラリの1つでは、シングルトンパターンを使用しています。彼らはHelperを使用してシングルトンをインスタンス化します。それはなぜ必要なのですか?なぜこのシングルトン実装はプライベートクラス(C++)を使用していますか?

ライブラリのヘッダファイル:彼らはシングルトンをインスタンス化する 'ヘルパー' を使用してあり

LibExample* LibExample::m_instance = NULL; 

LibExample* LibExample::getInstance() { 
    static Helper instance; 
    if(m_instance == NULL) { 
     m_instance = instance.libExampleInstance; 
     int ret = m_instance->init(); 
     if(ret < 0) { 
      m_instance = NULL; 
     } 
    } 
    return m_instance; 
} 
+2

私は想像しています:失敗した 'init'が完了するたびにメモリを解放/再割り当てせずに、インスタンス' m_instance'をヌルにする能力を持つこと。私が理解できないのは、多形性を伴わないスタックの代わりにヒープ上にメモリを割り当てる理由です。 –

+2

@ChrisR、 '私が理解できないのは、スタック上ではなくヒープ上にメモリを割り当てる理由です。私はこの特定のケースについてはわかりませんが、場合によっては(埋め込みで作業するとき)スタックのサイズが非常に大きく制限されていて、十分な大きさのオブジェクトのインスタンスが単純には収まらない場合があります。 – SingerOfTheFall

答えて

2

:.cppファイルで

Class LibExample { 

public: 
    static LibExample* getInstance(); 

private: 
    class Helper { 
    public: 
     Helper() { 
      libExampleInstance = new LibExample(); 
     } 
     ~Helper() { 
      delete libExampleInstance; 
     } 

     LibExample* libExampleInstance; 
    }; 

    static LibExample* m_instance; 

    LibExample(); 
    virtual ~LibExample(); 
    LibExample (const LibExample&) {}; 
    LibExample& operator=(const LibExample&) { 
     return *(LibExample::getInstance()); 
    } 
}; 

。それはなぜ必要なのですか?

これはありません。 Helperを使用してm_instance == NULLのテストを許可し、最初にgetInstanceを使用するときはinitを呼び出しますが、LibExampleコンストラクタでもinitを実行している可能性があります。あいまいな理由があるかもしれませんが、IMHOではこのデザインはちょうど複雑すぎます。

あなたは持っている可能性があり:

Class LibExample { 

public: 
    static LibExample* getInstance(); 

private: 
    LibExample(); 
    virtual ~LibExample(); 
    LibExample (const LibExample&) {}; 
    LibExample& operator=(const LibExample&) { 
     return *(LibExample::getInstance()); 
    } 
}; 

LibExample* LibExample::getInstance() { 
    static LibExample instance; 
    static LibExample* p_instance = NULL; 
    if(p_instance == NULL) { 
     int ret = instance.init(); 
     if(ret >= 0) { 
      p_instance = &instance; 
     } 
    } 
    return p_instance; 
} 

EDIT:コメントで@SingerOfTheFallで指摘したように

:私は、これはいくつかの種類を実装するために行われていると思います

後半の初期化:init()が初めて失敗した場合、シングレットそれ自体は再構築する必要はなく、次にインスタンスが呼び出されるときに自身を再初期化しようとします。

まだHelperは必要ありません。それに応じてコードを変更しました。

+2

これは、ある種の遅い初期化を実装するために行われると思います。 'init()'が初めて失敗した場合、シングルトン自体を再構築する必要はなく、次回自身を再初期化しようとしますインスタンスが呼び出される時刻。 – SingerOfTheFall

+0

@SingerOfあなたが正しいと私は私の答えでこれを統合しました – wasthishelpful

+0

私は新しいコードはまだ複数のスレッドが 'init'を呼び出すような問題があるかもしれないと思うので、ロックを回避することはできません。 – Danh

関連する問題