C ++のメモリ管理(new演算子/演算子新しい/オペレータ/配置新しい削除)

new演算子

新しい我々は通常のsizeofは、言語に組み込まれているとして、その意味を変更することはできません、機能は同じである同じ、new演算子(new演算子)を使用します

例えば:

string *ps = new string("Memory Management");

に相当

void *memory = operator new(sizeof(string)); // 得到未经处理的内存,为String对象 
call string::string("Memory Management") on *memory; // 调构造函数将字符串放到内存 
string *ps = static_cast<string*>(memory); // 使ps指针指向新的对象

new演算子は、常に2つのことを実行します。

1.メモリを割り当てるために、新しい適切な演算子を呼び出します

2.コール適切なコンストラクタ

次のコード:

class T{  
    public:  
    T(){  
        cout << "构造函数。" << endl;  
    }  

    ~T(){  
        cout << "析构函数。" << endl;  
    }  

    void * operator new(size_t sz){  

        T * t = (T*)malloc(sizeof(T));  //operator new就是简单的分配内存即可
        cout << "内存分配。" << endl;  
        return t;  
    }  

    void operator delete(void *p){  
        free(p);  
        cout << "内存释放。" << endl;  
        return;
    }  
};  

int main()  
{  
    T * t = new T(); // 先内存分配 ,再构造函数  
    delete t; // 先析构函数, 再内存释放  
    return 0;  
} 

業績

new演算子

new演算子のオーバーロードは、オブジェクトのためにメモリを割り当てる方法を変更することができます。new演算子は、必要なメモリ割り当てを行うための関数を呼び出すには、その動作を変更するには、この機能を書き換えたり上書きすることができます。呼び出された関数名にメモリを割り当てるための新しいオペレータは、オペレータ新しいです。

new演算子のオーバーロード

void * operator new(size_t sz)
{
    void* pm=malloc(sz);
    return pm;
}

戻り値の型がvoid *ポインタ、初期化されていないメモリの一種で、あなたはいくつかの値を格納するためのメモリを初期化することができますが、一般的にそうしていないポインタを返す前に、オペレータ新機能の1種類を書くことができます。あなたは、新しい関数の演算子をオーバーロードされたパラメータを追加することができますが、最初の引数はsize_t型でなければなりません。独自の新しいタイプは、ポインタ型のサイズに応じて計算することができます。

このようSTLのように、一般的には直接new演算子を呼び出すことはありませんが、時々使用:

Test *pt2=(Test*)::operator new(sizeof(Test));
::operator delete(pt2);

これは、メモリのテストタイプを収容するのに十分なオブジェクトへのポインタを返します。唯一のメモリを割り当てることがnew演算子。そして、コンストラクタ無関係で。新しいオブジェクトが新しい演算子に返された未処理のオペレータへのポインタを渡すと取り組んでいます。

例えば:

string *ps = new string("Memory Management");

に相当

void *memory = operator new(sizeof(string)); // 得到未经处理的内存,为String对象 
call string::string("Memory Management") on *memory; // 调构造函数将字符串放到内存 
string *ps = static_cast<string*>(memory); // 使ps指针指向新的对象

削除動作

、通話にデストラクタを削除し、その後オペレータコールを削除し、領域を解放することで、それは、上記の結果の実行から見ることができます。

彼らは削除し、独自の過負荷にすることができます

void operator delete(void *p)
{
    free(p);
}

new演算子

新しい[]演算子をオーバーロード

void* operator new[](size_t sz)
{
    void *pm=malloc(sz);
    return pm;
}

オペレータ新しいオペレータ新しい機能は、新しい新しいオペレータに、専用メモリを割り当てられて使用され、オペレータ新しい[]オブジェクトのための4つの新しいバイトより新しい[]を用い、新たな[]実際に割り当てられた複数であります数量

この数の4つのバイトはvoid *型new演算子の呼び出しパラメータとして追加されました;の大きさで、それは時にA * AP =新しいA5コールと言うことです。時間は、また新しい内部演算子と呼ばれ、効果は5を適用することです*大きさ(A)+メモリの4バイト。新しい[]オブジェクトのコンストラクタする各配列の初期化を呼び出します。また、新しい[]のポインタ型の独自の種類の大きさに応じて計算することができます。

削除呼び出すために適用するためにどれだけ記録するために使用される追加の4バイト、クッキーの同等の、[]はリリースがリリースされてどのくらいのスペースを知ることができます。

オペレータは、削除します

過負荷[]演算子を削除

void operator delete[](void *p)
{
    free(p);
}

オペレータに指定されたサイズのニーズが、[]指定されたサイズを必要としない、削除[]新しい、でもサイズに、それは意味がありません、リリース時には、上記の情報を解放するためにクッキーを読み取ることが有効ではありません。

配置新しいです

新しい2段階の散歩、コンストラクタを呼び出した後に、メモリを割り当てます。だから、それはメモリ、繰り返し建設デストラクタを維持することができますか?そのような複数の中間メモリの割り当てを省略してもよいです。メモリの応用として、オーバーヘッドがたくさんあります。C ++標準では考えていたので、彼らは新しい位置、新しい配置を提供しています。

int *p=(int*)malloc(sizeof(int)*10);
new(p)int(10);

10は、それがPの最初のスペースを置くと述べました。

void * operator new(size_t, void *location) 
{  
    return location; 
}

また、新しいオペレータ、追加の変数(バッファ)を使用する必要性を使用する方法です。new演算子は、暗黙的にオペレータの新しい機能と呼ばれるとき。それには、この変数を渡します。size_t型で必須のパラメータに加えて、呼ばれる演算子の新しい機能は、void *型のポインタはパラメータを受け入れる必要があります。オブジェクト構造によって占められるメモリ空間を指します。

あなたは下付き位置の代わり他の要素が必要な場合は、新たにリロードすることができます

void* operator new(size_t sz,void *ptr,int pos)    //第1个参数必须但不需要传递,由new自动计算的,第2个参数传递void*指针,第3个参数传递位置
{
    return &ptr[pos];
}

new(p,3)int(10);    //将10放在下标为3的空间中

新しいの実現のための内部メカニズム

我々は、すべての新しい2段階のプロセスが完了することを知っているが、この2つのステップにそれを達成するためにどのように新しいですか? 

私は1つのメモリを割り当てるために使用され、それが新たな二つの機能内部のパッケージだと思った、と1は、適切なコンストラクタを呼び出すこと。

しかし、実際には場合は、それは「隠された」新機能ではありません、コンパイラが自動的に新しいメモリ割り当て関数、コンストラクタに書き換えますありません。 

実際には、ここではより本質的な問題が指摘されなければならないがあります。新しいキーワードの性質は、キーワードインサイダーコンパイラの操作は、私たちの想像大きく異なる可能性があります。機能を過負荷状態にすることができ、オペレータは、キーワードをオペレータが理由の前に演算子オーバーロードを持たなければならない理由である、オーバーロードされていません。+(のInt a)は、新しい(INT a)は間違っています。 

簡単に言えば、新しい新しいコンパイラの動作中にコードの2つの部分、割り当てられたメモリ部分、コールの一部コンストラクタになります。

これは、実際に実験的に検証行うことができます。 

上記のコードの新しいTに参加し、ブレークポイントでマークされ、ステップのデバッグにより、その後、F10のステップは、ファーストクラスのnew演算子の中に発見され、次の行に新しいTの導入後、まだこの新しい行に残っていません、 F10は、コンストラクタに続行します。これは、新しいTラインが二度滞在したことを意味します。これは、コンパイラは2つの関数呼び出しに変換されたコードの新しいTラインを行うことを意味します。

第二の方法は、直接的に(推奨)コードを表示分解を検証することです。 

  私は実際に2つのコール、最初の呼び出しのT :: new演算子()があります見ることができます。2回目の呼び出しT :: T()。注意:本物の大要なし特定の関数名、のみ対応するアドレスを。VS表示関数名は、より便利な機能の1つです。

  私は実際に2つのコール、最初の呼び出しのT :: new演算子()があります見ることができます。2回目の呼び出しT :: T()。注意:本物の大要なし特定の関数名、のみ対応するアドレスを。VS表示関数名は、より便利な機能の1つです。

::新しいと新しいです

  内蔵メモリを割り当てることがnew演算子を隠すように設計されたグローバル・ネームスペース、があります。コンパイラはこれに新しい、この新しいキーワードのデフォルトの演算子と対応するコンストラクタを翻訳します。

  しかし、いくつかのケースでは、ユーザー自身がクラスのオーバーロード演算子に新しいなり、この場合には、コンパイラはデフォルトのクラスオーバーロードされた演算子を使用します(新しい基本的にコンパイラが出て内側から名前空間から見えますので、 )あなたが欲しい機能、最初に選択します。

  私たちは、デフォルトのoperator newを引き続き使用する場合、書かれるべき::新しい文字通りの意味は、新しい名前空間演算子での最外層を呼び出すことです

 これは、新しい、最も外側(またデフォルト)オペレータはまた、過負荷にすることができることを言及する価値があります。このようにして、我々は新しいのすべての部分の動作を変更することができます。

概要

C ++動的メモリ管理はnewとdelete演算子によって行われます。

図は、新しいの意味を説明して削除します。

newとdeleteとmallocとfreeなど、ペアで使用されます。

これは文字列* S =新しい文字列(「値」)であり、フレーズの内部表現のために:

これは、描画することができます。

新しい呼び出しシーケンス内の(オブジェクトの初期化): - 演算子新しい - malloc関数 - 新しいコンストラクタ(第1空間アプリケーション、そしてコンストラクタを呼び出します)

新しい呼び出しシーケンス内の(初期いくつかのオブジェクト):新しい - 演算子新しい[] - のmalloc - コンストラクタ(最初のアプリケーション+4空間のすべてのメンバーの配列は、配列内の各オブジェクトは、コンストラクタを呼び出すために)

(単一のオブジェクトを削除する場合)呼び出し順序場合オブジェクトを削除:削除 - デストラクタ - オペレータ削除 - (最初の空き領域次に、デストラクタを呼び出し)フリー

(複数のオブジェクトを削除した場合)呼び出しの順序と、オブジェクトを削除:削除[] - デストラクタ - オペレータ削除[] - フリー(最初にアレイ全体を放し、各配列オブジェクトのデストラクタを呼び出します空間、マルチアプリケーション、4バイトの空間情報)

両者の違いを新しい/削除し、malloc関数/無料

1.彼らは、動的なメモリ管理ポータルです。

2.malloc /自由は、新しい/ C ++演算子を削除し、C / C ++標準ライブラリの関数です。

3.malloc /自由だけで動的に割り当てられたメモリ空間/フリースペース。新は/(クリーンメンバー)を初期化してクリーンアップするデストラクタを呼び出すことになる割り当てられたスペースに加えて、削除します。

4.malloc /無料の手計算と型サイズのvoid *の値を返し、新しい/ポインタの対応するタイプの大きさを計算することができる自分のタイプを削除します。

基礎となる5.new/delete呼び出しのmalloc /無料。

フリースペースの後6.malloc /アプリケーションが空の刑を宣告された、新しい/削除する必要はありません。

タイプでは、バイトを直接7.new数とのmalloc番号。

おすすめ

転載: www.cnblogs.com/WindSun/p/11445844.html