C++のnewキーワード

13591 ワード

newはプログラムの実行中に変数にメモリを一時的に割り当てるためのC++キーワードであることはよく知られていますが、C言語のmallocとどのような違いがあるのでしょうか.それに比べてnewを推奨するのはなぜですか.
c++11
 throwing(1) void* operator new (std::size_t size);
  nothrow(2) void* operator new (std::size_t size, const std::nothrow_t& nothrow_value) noexcept;
placement(3) void* operator new (std::size_t size, void* ptr) noexcept;

void *malloc(size_t size);

1.申請したメモリーの場所
Openator newは、フリーストレージ領域からオブジェクトにメモリ領域を動的に割り当て、mallocはスタックからメモリを動的に割り当てます.
フリーストレージ領域はC++operator newに基づく抽象概念であり、operator newによって申請されたメモリ、すなわちフリーストレージ領域である.スタックはコンピュータのオペレーティングシステムの用語で、オペレーティングシステムが維持した特殊なメモリで、プログラムのメモリの動的な割り当てに用いられ、C言語はmallocを使ってスタックからメモリを割り当てます.
freeを使用して、割り当てられた対応するメモリを解放します. 
ではnewはスタックにメモリを動的に割り当てることができますか?これはoperator newの実装の詳細に依存し、フリーストレージ領域はスタックだけでなく静的ストレージ領域であってもよく、operator newがどこでオブジェクトにメモリを割り当てているかを見ることができます.newはオブジェクトにメモリを割り当てないこともできます! 
new (place_address) type

place_addressは、メモリアドレスを表すポインタです.newオペレータを1つのアドレスで呼び出すと、newオペレータは特殊なoperator new、すなわち上のpalcement(3)を呼び出す.
void* operator new (std::size_t size, void *ptr); //     operator new     

このoperator newはメモリを割り当てず、ポインタの実パラメータを簡単に返し、new式でplace_に責任を負います.addressが指定したアドレスは、オブジェクトの初期化作業を行います.
2.戻り型セキュリティ
Operator newメモリ割り当てに成功した場合、オブジェクトタイプのポインタが返され、タイプ変換を行う必要がないため、タイプセキュリティに合致するオペレータです.mallocメモリ割り当ては正常に返され(void*)、強制タイプ変換によって必要なタイプに変換する必要があります.
3.メモリの割り当てに失敗した場合の戻り値
newメモリ割り当てに失敗するとbac_が放出されますalloc exception、NULLは返されません.mallocメモリの割り当てに失敗した場合はNULLを返します.
C言語を使用する場合、mallocがメモリを割り当てた後、割り当てが成功したかどうかを判断することに慣れています.
int *a = (int *)malloc(sizeof(int));
if (a == NULL) {
    // ...
} else {
    // ...
}

C++プログラムを書くとき、C言語の習慣に従って書くことがあります.int*a=new int()です.if (a == NULL) {//... } else {//... }ああ、実際には何の意味もありません.newはNULLを返さないので、プログラムはifに実行してメモリの割り当てに成功したことを説明することができます.そうしないと、とっくに異常を投げています.正しい方法は異常メカニズムを使うことです
try {
    int *a = new int();
} catch (bac_alloc) {
    // ...
}

4.メモリサイズを指定する必要があるか
newオペレータを使用してメモリを申請するときにメモリブロックサイズを指定する必要はありません.コンパイラはタイプ情報に基づいて自分で計算しますが、mallocは必要なメモリサイズを明示的に示す必要があります.
mallocはメモリのみを割り当て、freeはメモリのみを回収し、バイト単位でメモリ操作を行い、構造と構造関数を実行しない.Newはオブジェクトのコンストラクション関数を呼び出し、deleteは対応するコンストラクション関数を呼び出し、メモリの割り当てと解放を特定のタイプ単位で行うことができます.
class A {
public:
    A() {} 
    ~A() {}
}
A *ptr_new = new A;
A *ptr_malloc = (A *)malloc(sizeof(A)); //       malloc                     。

5.構築/解析関数を呼び出すかどうか
Openator newオペレータを使用してオブジェクトメモリを割り当てるには、次の3つのステップがあります.
  • operator new関数(配列がoperator new[]である場合)を呼び出し、十分な大きさの元の名前のないメモリ領域を割り当てます.
  • コンパイラは、指定したタイプのオブジェクトを構築し、初期化するために、対応するコンストラクション関数を実行します.
  • オブジェクトの構造が完了すると、そのオブジェクトを指すポインタが返されます.

  • Openator deleteオペレータを使用してオブジェクトメモリを解放するには、次の2つのステップがあります.
  • は、オブジェクトの構造関数を呼び出します.
  • コンパイラはoperator delete(またはoperator delete[])関数を呼び出してメモリ領域を解放します.

  • 要するにnew/deleteはオブジェクトのコンストラクション関数/コンストラクション関数を呼び出してオブジェクトのコンストラクション/コンストラクションを完了しますが、malloc/freeはしません.
    mallocはメモリ初期化の特性を備えていないが、newは単一のタイプの変数を申請する際に初期化することができる.
    6.配列の処理
    C++はnew[]/delete[]専用処理配列タイプを提供
    A *ptr_single new A;
    A *ptr_arr = new A[10];
    delete ptr_single;
    delete[] ptr_arr;

    Newの配列のサポートは、各配列要素に対してそれぞれ構造関数を呼び出して初期化し、オブジェクトを解放するときに各オブジェクトに対して構造関数を呼び出すことに現れます.注意delete[]はnew[]と組み合わせて使用します.そうしないと、配列オブジェクトの一部が解放され、メモリが漏洩します.
    mallocはあなたがこのメモリに置く配列が単一のデータなのか分からないが、どうせ元のメモリをあげて、メモリのアドレスを返します.配列のメモリを動的に割り当てるには、配列サイズを手動で指定する必要があります.
    int * ptr = (int *)malloc(sizeof(int) * 10);

    7.newとmallocは互いに呼び出すことができるか
    operator new/operator deleteの実装はmallocに基づいてもよいが、mallocの実装はnewを呼び出すことはできない.
    malloc/freeはC言語で提供される標準ライブラリ関数で、使用時にヘッダファイルを含め、C/C++で通用し、上書きすることができる.
    // for C 
    #include 
    
    // for C++
    #include 

    新/deleteは演算子であり、キーワードでもあり、C++の一部であり、C++でのみ使用でき、リロードできます.
    void * operator new (sieze_t size)
    {
        if(void * mem = malloc(size)
            return mem;
        else
            throw bad_alloc();
    }
    void operator delete(void *mem) noexcept
    {
        free(mem);
    }

    8.リロード可能か
    Openartor new/operator deleteは再ロードできます.標準ライブラリはoperator new/operator deleteを定義した12のリロードバージョンです
    // new
       throwing (1)    void* operator new (std::size_t size);
        nothrow (2)    void* operator new (std::size_t size, const std::nothrow_t& nothrow_value) noexcept;
    placement (3)    void* operator new (std::size_t size, void* ptr) noexcept;
    
       throwing (1)    void* operator new[] (std::size_t size);
        nothrow (2)    void* operator new[] (std::size_t size, const std::nothrow_t& nothrow_value) noexcept;
    placement (3)    void* operator new[] (std::size_t size, void* ptr) noexcept;
    
    // delete
        ordinary (1)    void operator delete (void* ptr) noexcept;
        nothrow (2)    void operator delete (void* ptr, const std::nothrow_t& nothrow_constant) noexcept;
    placement (3)    void operator delete (void* ptr, void* voidptr2) noexcept;
    
       ordinary (1)    void operator delete[] (void* ptr) noexcept;
        nothrow (2)    void operator delete[] (void* ptr, const std::nothrow_t& nothrow_constant) noexcept;
    placement (3)    void operator delete[] (void* ptr, void* voidptr2) noexcept;

    カスタムバージョンがグローバル役割ドメインまたはクラス役割ドメインに存在する必要があることを前提として、上記の関数のいずれかをカスタマイズできます.malloc/freeではリロードは許可されていません.
    9.メモリを直感的に再割り当てできるか
    mallocで割り当てられたメモリを使用すると、使用中にメモリが不足していることが判明した場合、realloc関数を使用してメモリ再割り当てを行い、メモリの拡張を実現できます.
    reallocは、現在のポインタが指すメモリに十分な連続空間があるかどうかを判断し、ある場合は、割り当て可能なメモリアドレスをその場で拡大し、元のアドレスポインタに戻る.そうでない場合は、新しく指定したサイズでスペースを割り当て、既存のデータを最初から最後まで新しい割り当てられたメモリ領域にコピーし、元のメモリ領域を解放します.
    newはこのような直感的なセット施設でメモリを拡張していません.
    10.メモリ不足の処理方法をカスタマイズできるか
    Openator newが例外を投げ出す前に、パラメータがなく戻り値がない関数であるエラー処理関数を指すポインタタイプであるnew-handlerというユーザー指定のエラー処理関数が呼び出されます.
    namespace std{
        typedef void (*new_handler)();
    } 

    エラー処理関数を指定するには、set_を呼び出す必要があります.new_handlerこれはstdネーミングスペースに宣言された標準ライブラリ関数namespace std{new_handler set_new_handler(new_handler p)throw()です. 
    namespace std{
        new_handler set_new_handler(new_handler p) throw();
    }  

    set_new_handlerのパラメータはnew_handlerポインタは、operator newが十分なメモリを割り当てられない場合に呼び出される関数を指します.その戻り値もポインタでset_を指しますnew_handlerが呼び出される前に実行中(ただし、すぐに置換が発生する)のnew_handler関数.
    mallocの場合、ユーザはメモリが割り当てられていない場合にどのように操作するかをプログラミングすることができず、mallocがNULLを返すのを見るしかない.