c++オブジェクト向けoperator new学習ノート

2987 ワード

実際のコードではnewの姿は少ない、比較的古いc++コンパイラ環境でもauto_ptrの管理メモリが提供されている.しかし、c++は結局、下位層に近いいくつかの例証は、クラスのパッケージに追加の負担を加えていないことであり、c++オブジェクトモデルは依然として連続したメモリアドレスに1つずつマッピングされている.メモリの割り当て方法については、制御権はプログラマーの手に残っている.やはりよく理解する必要がある.
operator newの再ロードのメリット
  • は運転上のエラーを検出するために使用される:例えば比較的よく見られる配列の境界を越えたセグメントエラーは、システムがdumpを理解しない場合があるが、このエラーは隠されている.これによりメモリリークを実現することができる.
  • は性能を提供する:この点が最も重要で、システムが提供するモデルのメモリ分配行為は一刀切で、異なるデータはメモリ分配器に対する需要が異なり、システムが提供するのは必ずしも最適ではない.
  • は使用統計データを収集する.

  • set_new_handler operator newと同様に、メモリ割り当てに失敗するの後に実行を呼び出すためのbad_allocが提供される.システムが提供するプロトタイプは、デフォルトのグローバルな戻りポインタがnullptrであるか、必要に応じてリロードするか、クラスの内部に置くかのいずれかである.
    std::new_handler set_new_handler(new_handler); 

    一般的にこのポインタstd::new_handlerはグローバルに値を付与しません.もしそうであれば、他のモジュールに影響を与えるに違いありません.人の良いメモリは最大bad_allocグローバルポインタを割り当てることができません.値を付与すると、どこに行って何を実行するか分かりません.だから、自分で返却することが基本原則になります.基本的な流れは以下の通りです.
  • は、元のグローバルポインタnew_handlerを取得する、
  • を記憶する.
  • 新しいnew_handlerに設定
  • を使用する.
  • は自分で使い切って(役割ドメイン内/class内)、最初に保存した返却をシステムに設定.

  • もちろん、ここではマルチスレッドの問題についても言及するが、現在議論されているものとは関係なく、まず考慮しない.このような資源の管理は最後に返還され、ちょうどクラス構造/構造関数を用いて完成することができる.基本形式は以下の通りです.
    class NewHandlerHolder {
    public:
        //                     .
        explicit NewHandlerHolder(std::new_handler nh) 
            : handler(nh) {}
        ~NewHandlerHolder() {
            std::set_new_handler(handler);
        }   
    private:
        std::new_handler handler;
    };
     
    class Widget 
    {
    public:
        void *operator new(size_t size) throw(std::bad_alloc);
     
    private:
        static std::new_handler currentHandler;
    };
     
    std::new_handler Widget::currentHandler = 
        [](){
            cout<

    オブジェクトoperator newのリロード
    簡略化版では、operator new形式の再起動のみが示されています.本来、動作の不一致(グローバルな呼び出しワード構築を呼び出す場合もある)を避けるためには、すべてのリロードが妥当です.
    class INTType
    {     
    public: 
        INTType():x(0) {}
        static void *operator new(size_t size) throw(std::bad_alloc);
          
        //...
    private:
        int x;
    };    

    リロードオブジェクトoperator newベストプラクティス
    システムに複数のクラスがグローバルoperator newをリロードする必要がある場合、実際にはクラスをベースクラスとして新たに抽象化することができ、サブクラスはインタフェースを継承すればよい.また、コードを節約するだけでなく、各クラスのインスタンスデータを独占する必要がある場合は、クラスプログラミングテンプレートクラスを独立することができる.
    template    // T      ,        
    class NewHandlerSupport {
    public:
        void *operator new(size_t size) throw(std::bad_alloc);
        void *operator new[](size_t size) throw(std::bad_alloc);
     
    protected:
        static std::new_handler currentHandler;
    };
    //         
    class WidgetHander : public NewHandlerSupport

    まとめ
    グローバルなものをリロードする必要はなく、影響範囲が大きい.クラスに入れてリロードするのが望ましい現在メモリの統計と記録に対してすべて比較的に良くて成熟した方案があるべきで、またスマートポインタの導入がメモリの使用に対してもメモリの漏洩が発生することが少ないなどの問題のためoperator newリロードに対する強い需要は性能の上の昇格だけから来て、これは便利でやはり引き続き深く学ぶことができるboost::Pool参照先: