operator newとnew operator

5172 ワード

C++のoperator newとnew operator、似ているように見える姉妹ですが、雲泥の差があります.
operator new
(1)要求された空間のみを割り当て、関連オブジェクトのコンストラクタを呼び出さない.要求された割り当てられた空間を満たすことができない場合、
->newがあればhandler、new_を呼び出すhandler、そうでなければ
->例外を放出しない(nothrowパラメータで表す)必要がない場合はbad_alloc例外を実行します.そうでない場合は
->0を返します
(2)リロード可能
(3)リロードの場合、戻りタイプはvoid*として宣言する必要があります.
(4)リロードの場合、最初のパラメータタイプは、size_tのタイプである表現に空間を割り当てるサイズ(バイト)でなければならない
(5)リロード時に他のパラメータを持ち込むことができる
new operator
(1)operator newを呼び出して十分な空間を割り当て,関連オブジェクトのコンストラクション関数を呼び出す.
(2)重荷重不可
従って、operator deleteはdelete operatorと類似の特性を有する.
例を挙げるclass X 
{
public:
…………
    static void* operator new(size_t size)
{
    return ::operator new(size);
}
static void operator delete(void* pointee)
{
    ::operator delete(pointee);
}
…………
};
X* px = new X();

行コードのnewはnew operatorであり、クラスXのoperator newが呼び出され、クラスのオブジェクトに空間が割り当てられ、現在のインスタンスのコンストラクション関数が呼び出されます.delete px;
行コードのdeleteはdelete operatorであり、インスタンスの構造関数を呼び出し、クラスXのoperator deleteを呼び出してインスタンスが占有するスペースを解放します.
新operatorとdelete operatorの行為は変えられないし、変えるべきではない.これはC++標準の約束だ.一方、operator newはoperator deleteとC言語のmallocとfreeに対応し、空間の割り当てと解放だけを担当しています.ただし、operator newを使用して割り当てられたスペースは、メモリの登録方法が異なるため、freeを使用することなくoperator deleteを使用して解放する必要があります.逆に同じです.
operator newとoperator deleteをリロードしてメモリ管理の異なる要件を実現できますが、new operatorまたはdelete operatorをリロードして動作を変更することはできません.
operator newをリロードすると、より多くのパラメータが提供され、newのオブジェクトの場合、キーワードnewの後のカッコで追加のパラメータが渡されます.例えば以下のクラスclass A 
{
public:
    …………
    static void* operator new(size_t size, const string& example)
{
    cout << example << endl;
    return ::operator new(size);
}
…………
};
A* pa = new (“This will be printed out in operator new”) A();

新しい規格のC++は、このような方法でnothrowというパラメータを渡すことを可能にし、オブジェクトに空間を割り当てることに失敗した場合、例外を投げ出さずに0を返し、古い規格newの動作と互換性があることを示します.たとえばclass B {};
B* pb = new (nothrow) B();

もちろん、デフォルトのoperator newオペレータを使用するクラスのみです.operator newをリロードしたクラス(例えば上のXやA)については、nothrowパラメータを受け入れられると宣言しないと、C++スタンダードがもたらすプレゼントを楽しむことはできません.
 
Operator newの6種類のリロード形式
p=new P();このようなコードの場合、実際には2つのステップがあり、まずメモリを割り当て、割り当てられたメモリの上にクラスメンバーを初期化する.第2歩は構造関数が完成し、第1歩はnew関数の仕事である.グローバルなnewには6つのリロード形式があり、void*operator new(std::size_t count)throw(std::bad_alloc);//一般的なバージョンvoid*operator new(std::size_t count,//旧バージョンのnew const std::nothrow_t&)throw();//メモリ割り当てに失敗しても異常void*operator new(std::size_t count,void*ptr)throw();//placementバージョンvoid*operator new[](std::size_t count)/throw(std::bad_alloc);void *operator new[](std::size_t count, //    const std::nothrow_t&) throw(); void *operator new[](std::size_t count, void *ptr) throw(); だから、さっきの使い方はnew関数を使うリロード形式です.Aというオブジェクトが同じようにnew関数をリロードする化を行うと、メンバ関数として優先的に呼び出される.C++の各種new紹介1.新Tの第1種のnewは最も簡単で、クラスの(再ロードされた場合)あるいはグローバルなoperator newを呼び出して空間を割り当てて、それからタイプの後ろの列のパラメータで構造関数を呼び出して、使い方はnew TypeName(initial_args_list)です.パラメータがない場合、括弧は一般的に省略できる.例えばint*p=new int;int *p=new int(10); int *p=new foo("hello"); deleteを呼び出すことで破棄:delete p;2.new T[]このようなnewは動的オブジェクト配列を作成するために使用され、オブジェクトのoperator new[]を呼び出してメモリを割り当て(なければoperator newを呼び出し、検索順序は同じ)、次にオブジェクトのデフォルト構造関数を呼び出して各オブジェクトの使用法を初期化する:new Type Name[num_of_objects];例えばint*p=new int[10];破棄時にoperator delete[]3を使用する.new()Tとnew()T[]パラメータ付きnewです.この形式のnewはoperator new(size_t,OtherType)を呼び出してメモリを割り当てます.ここでOtherTypeはnewカッコのパラメータのタイプと互換性があります.この構文は通常、operator new(size_t,void*)が定義されている場合、placement newと呼ばれる特定のアドレスコンポーネントオブジェクトに使用されます.通常、コンパイラはヘッダファイルを含む実装を提供しています.この実装はパラメータの指定されたアドレスを簡単に返すだけです.したがって、new()演算子はカッコ内のアドレスにオブジェクトを作成します.説明する必要があります.2番目のパラメータはvoid*ではなく、識別できる合法的なタイプです.この場合、C++のリロードメカニズムによってそのoperator newを呼び出すことが決定される.もちろん、char data[1000][sizeof(foo)]のようなnewの動作を決定するために、独自のoperator new(size_,Type)を提供することができる.inline void* operator new(size_t ,int n) {         return data[n]; } このような興味深い構文を使用して、foo*p=new(6)foo()//オブジェクトをdataの6番目のユニットに作成するのは確かに興味深い標準ライブラリはnothrowの実装も提供しています:void*operator new(std::size_t,const std::nothrow_t&)throw();void* operator new[](std::size_t, const std::nothrow_t&) throw(); 呼び出しnewが失敗したときに異常new(nothrow)int(10)を投げ出さないことを実現できます.//nothrowはstd::nothrow_tのインスタンスplacement newで作成されたオブジェクトは直接deleteで破棄するのではなく、オブジェクトの分析関数を呼び出してオブジェクトを破棄します.オブジェクトが占めるメモリがどのように処理されるかは、このメモリの具体的なソース4によって決まります.Openator new(size_t)という演算子は、パラメータにサイズのメモリを割り当ててヘッダアドレスを返します.この演算子をカスタムクラスに再ロードする方法は、クラスにvoid*operator new(size_t size){//ここでメモリを割り当ててアドレスを返す}を宣言して宣言するかどうかにかかわらず、クラスにリロードされた各種operator newとoperator deleteはstatic属性を持つ一般的にoperator newを直接呼び出す必要はありません.元のメモリを直接割り当てる(これはCのmallocに似ています)衝突した場合にグローバルのoperatorを呼び出す必要があります::役割ドメイン演算子:::operator new(1000);//1000バイトの割り当てで返されるメモリを回収する必要がある場合は、対応するoperator delete 5を呼び出す.Operator new[](size_t)これも割り当てメモリであり、配列、すなわちnew T[]に特化した形式にすぎない.もちろん、必要に応じて明示的に6を呼び出すことができる.operator new(size_t size,OtherType other_value)とoperator new[](size_t size,OtherType other_value)上記のnew()を参照する上で強調する必要があるのは、newはオブジェクトを作成してメモリを割り当てるために使用され、その動作は変更できず、様々なoperator newを変更することができ、operator newを再ロードすることでメモリ割り当てスキームを実現することができることである.