C++におけるoperator newおよびoperator deleteは、オブジェクトをnewおよびdelete演算子を使用して配置および削除する際に呼び出されるメモリの割り当ておよび解放関数です。デフォルトでは標準アロケータを使用しますが、クラス内ではメモリ割り当てを細かく制御するためにオーバーロードできます。
operator newは、コンストラクタを呼ばずに「生」のメモリ領域を割り当てます。operator deleteは、オブジェクトのデストラクタが完了した後にメモリを解放します。operator newをオーバーライドすることで、そのクラスのオブジェクトに対してメモリの使用を最適化できます(例えば、オブジェクトプール、トレース、ブロックの再利用など)。#include <iostream> class TrackAlloc { public: void* operator new(size_t size) { std::cout << "TrackAlloc::new for " << size << " bytes "; return ::operator new(size); } void operator delete(void* ptr) { std::cout << "TrackAlloc::delete "; ::operator delete(ptr); } };
"クラス内でオペレーターnewをオーバーライドし、その後、派生クラスの変数を介してオブジェクトを作成した場合、どのバージョンのoperator newが呼び出されますか?"
答え: オブジェクトが作成されるクラスのoperator newが呼び出されます。もし派生クラスにoperator newが実装されていない場合、基底クラスまたはグローバルバージョンの適切なバージョンを探す試みが行われます。
例:
struct Base { void* operator new(size_t s) { std::cout << "Base new "; return ::operator new(s); } }; struct Derived : Base {}; Derived* p = new Derived; // Base::operator newが呼び出されます!
物語
開発者は例外処理の正しいサポートなしにoperator new/deleteをオーバーロードしました。コンストラクタ内で例外がスローされた場合、メモリが解放されず、リークが発生しました。
物語
operator new[]およびoperator delete[]を不適切に実装しました:配列を保持するクラスでは、新しい実装が呼び出されず、デフォルトのバージョンが使用されることで、メモリの割り当てと解放のロジックが同期されなくなりました。
物語
グローバルoperator newのオーバーライドはサードパーティライブラリの機能に影響を与えました:すべてのオブジェクト(一時オブジェクトおよびSTLのオブジェクトを含む)がログを記録するアロケータを介して割り当てられ、アプリケーションコアのパフォーマンスが著しく低下しました。