オリジナル住所:https://blog.csdn.net/linux_ever/article/details/50533149
新しいとmallocの間に10ポイントの差
メモリ位置の1アプリケーション
フリーストア(フリーストア)からオブジェクトの新しいオペレータ動的に割り当てられたメモリ空間は、malloc関数は、動的ヒープからメモリを割り当てます。C ++無料のストアは、new演算子を使用してメモリ・アプリケーションのために、メモリがフリーストアでnew演算子の抽象化に基づいています。用語ヒープは、オペレーティングシステム、オペレーティングシステムは、特殊なメモリによって保持され、プログラムのために動的に割り当てられるメモリであり、C言語のmalloc関数は、ヒープから割り当てられたメモリの対応する遊離放出の使用メモリを割り当てます。
無料の店がnew演算子の実装の詳細に依存し、(新しいメモリを動的にヒープ上に割り当てることができるかどうかを疑問に相当)のヒープであるかどうかそう。無料店舗だけでなく、山、また新しいオペレータがオブジェクトにメモリを割り当てるために場所を見ることができない静的な記憶領域であってもよいことがあります。
でも、特に新しいと、オブジェクトにメモリを割り当てることができません!これを行うことができ、新たな機能を見つけます。
1 新しい(place_address)タイプ
メモリアドレスのポインタ代表としてplace_address。このようなアドレスは上記のみnew演算子を使用すると、新しい特定のオペレータを呼び出すための新オペレータは、このバージョンは以下の通りであります:
1 無効 * 演算子 新新(size_tの、無効 *)// new演算子のこのバージョンを再定義することはできません
任意のメモリを割り当てませんnew演算子は、それは単に右式はplace_address指定されたアドレスに新しい作業オブジェクトを開始するための責任があり、ポインタ引数を返します。
2.セキュリティのタイプを返します
オブジェクト・タイプへのポインタを返すときに成功した新しいオペレータメモリ割り当て、厳格なマッチングのオブジェクトタイプは、変換のタイプを必要とせず、それはオペレータの安全の新しいタイプに沿ったものです。malloc関数のメモリ割り当ては*、*は、私たちは無効となります強制転換を通じて必要なポインタ型に変換する必要が成功したリターン無効です。
セキュリティの種類は、私が許可されていないメモリ領域の方法を試みないメモリのセキュリティ、タイプセーフなコードとほぼ同等であることができます。セキュリティの種類のC ++は、言いたいことがたくさんあることができます。
3.場合、メモリ割り当ての失敗の戻り値
新しいメモリの割り当てに失敗した場合は、例外がスローされますbac_alloc、それはNULLを返しません。NULLときのmallocメモリ割り当ての失敗を返します。
C言語を使用している場合、我々は、malloc関数はメモリの割り当てが成功した配分するかを決定するために使用されます。
1 INT * A =(INT *)はmalloc(はsizeof(INT ))。 2 であれば(NULL == A) 3 { 4 ... 5 } 6 そう 7 { 8 ... 9 }
C言語からのキャンプに初心者C ++ C ++にこの習慣を入れることができます:
1つの int型 * A = 新しい int型(); 2 であれば(NULL == A) 3 { 4 ... 5 } 6 そう 7 { 8 ... 9 }
実際には、そうする新しいはNULLを返すことはありませんので、意味がない、と失敗が例外をスローしているならば文は、成功したメモリ割り当てに説明されている場合は、プログラムが実行することができます。正しい方法は、例外メカニズムを使用することです。
1 試みる 2 { 3 int型 * A = 新た INT ()。 4 } 5 キャッチ(bad_alloc) 6 { 7 ... 8 }
あなたが道に例外的な基礎を理解したい場合は、あなたが見ることができますhttp://www.cnblogs.com/QG-whz/p/5136883.html C ++例外機構解析を。
4.メモリーのサイズを指定する必要がありますか
メモリ割り当てられたメモリブロックのサイズのための新しい演算子を指定することが必要な場合、コンパイラは、情報の種類に応じて算出、それには、明示的にメモリサイズが必要なことをmalloc必要であると仮定します。
1 クラスA {...} 2 A = * PTR 新しい新A、 3 A * PTR =(*)はmalloc(はsizeof(A)); // 明示的に必要なメモリサイズはsizeof(A)を指定する必要があります。
もちろん、私たちはカスタムタイプのためにメモリを割り当てるためにmalloc関数を使用するために私はここに非常に適していない、次のものを参照してください。
5.コンストラクタ/デストラクタを呼び出すかどうか
オブジェクトが3つの段階に供されるときにメモリを割り当てますnew演算子を使用します:
- ステップ:オペレータ新しい関数を呼び出すには、(オペレータのための新しい配列が[])特定の型のオブジェクトを格納するための十分な大きさ、元の、無名のメモリ領域を割り当てます。
- ステップ2:オブジェクトを構築するための適切なコンパイラコンストラクタ、およびその入ってくる初期値を実行します。
- 第三:オブジェクトの建設が完了し、オブジェクトへのポインタを返します。
オブジェクトのメモリを解放するには、delete演算子を使用したときに、2つのステップを経ます:
- 最初のステップ:呼び出し元のオブジェクトのデストラクタ。
- ステップ2:コンパイラは、delete演算子(または演算子[]を削除)のメモリ空間を解放する関数を呼び出します。
要約すると、コンストラクタ新しい/削除するオブジェクトは、コンストラクタ/デストラクタのオブジェクトを完了するために、/デストラクタを呼び出します。malloc関数はしていません。あなたが長すぎるったらしいされることはありません場合は、私の例で見ることができます:
1 クラス2 { 3 公共: 4 A():(1)、B(1.11 ){} 5 プライベート: 6 INT 。 7 ダブルB; 8 }。 9 INT )(メイン 10 { 11 A * PTR =(*)はmalloc(はsizeof (A))。 12 リターン0 ; 13 }
見返りにブレークポイントを設定し、メモリは、コンテンツを見るptrが。
デフォルトコンストラクタは、カスタムよりも、A、BはC ++カスタムタイプを処理するために自由にmalloc /を使用し、私は上記の言った理由である、初期化されていないの値のデータメンバーが実際に、不適切であるため、呼び出されていない見ることができます通常は/構築標準ライブラリに必要なタイプは、不適当すべてのタイプを破壊。
また、新しいオブジェクトを割り当てるために使用する場合:
1 INT メイン() 2 { 3 A * PTR = 新しいA。 4 }
見つけることができるプログラムによって生成されたアセンブリコードを確認し、デフォルトコンストラクタが呼び出されます。
6.アレイのプロセス
C ++が提供する新たな[]および[]配列型と特異的に対処するために削除します。
PTR = * 新しい新しい A [ 10 ]; // オブジェクトを割り当てる10 A
新しい[]に割り当てられたメモリを使用することで解放されるように[]削除を使用する必要があります。
削除 [] PTRを。
N- EWは、各オブジェクトは、デストラクタ解放オブジェクトを呼び出すためのコンストラクタは、配列の各要素を初期化し、そのそれぞれの呼び出しでアレイのサポートを反映しています。それは新たな[]の使用を支持する、またはメモリリークによって引き起こされる現象のオブジェクトの部分解放の配列を見つけるに[]削除注意。
malloc関数として、あなたはそれを知っているし、とにかく、メモリアレイまたは何か他の作品を置くために、それはあなたのビン上のメモリアドレスを与えて、あなたのオリジナルのメモリを提供します。あなたが動的なメモリ割り当ての配列をしたいのであれば、我々はまた、手動で配列のサイズをカスタマイズする必要があります。
INT * PTR =(INT *)はmalloc(はsizeof(INT)); // 10個の要素のアレイを割り当てるINT
malloc関数と7.newは、お互いを呼び出すことができるかどうか
operator new /operator delete的实现可以基于malloc,而malloc的实现不可以去调用new。下面是编写operator new /operator delete 的一种简单方式,其他版本也与之类似:
1 void * operator new (sieze_t size) 2 { 3 if(void * mem = malloc(size) 4 return mem; 5 else 6 throw bad_alloc(); 7 } 8 void operator delete(void *mem) noexcept 9 { 10 free(mem); 11 }
8.是否可以被重载
opeartor new /operator delete可以被重载。标准库是定义了operator new函数和operator delete函数的8个重载版本:
1 //这些版本可能抛出异常 2 void * operator new(size_t); 3 void * operator new[](size_t); 4 void * operator delete (void * )noexcept; 5 void * operator delete[](void *0)noexcept; 6 //这些版本承诺不抛出异常 7 void * operator new(size_t ,nothrow_t&) noexcept; 8 void * operator new[](size_t, nothrow_t& ); 9 void * operator delete (void *,nothrow_t& )noexcept; 10 void * operator delete[](void *0,nothrow_t& )noexcept;
我们可以自定义上面函数版本中的任意一个,前提是自定义版本必须位于全局作用域或者类作用域中。太细节的东西不在这里讲述,总之,我们知道我们有足够的自由去重载operator new /operator delete ,以决定我们的new与delete如何为对象分配内存,如何回收对象。
而malloc/free并不允许重载。
9. 能够直观地重新分配内存
使用malloc分配的内存后,如果在使用过程中发现内存不足,可以使用realloc函数进行内存重新分配实现内存的扩充。realloc先判断当前的指针所指内存是否有足够的连续空间,如果有,原地扩大可分配的内存地址,并且返回原来的地址指针;如果空间不够,先按照新指定的大小分配空间,将原有数据从头到尾拷贝到新分配的内存区域,而后释放原来的内存区域。
new没有这样直观的配套设施来扩充内存。
10. 客户处理内存分配不足
在operator new抛出异常以反映一个未获得满足的需求之前,它会先调用一个用户指定的错误处理函数,这就是new-handler。new_handler是一个指针类型:
1 namespace std
2 {
3 typedef void (*new_handler)();
4 }
指向了一个没有参数没有返回值的函数,即为错误处理函数。为了指定错误处理函数,客户需要调用set_new_handler,这是一个声明于的一个标准库函数:
1 namespace std 2 { 3 new_handler set_new_handler(new_handler p ) throw(); 4 }
set_new_handler的参数为new_handler指针,指向了operator new 无法分配足够内存时该调用的函数。其返回值也是个指针,指向set_new_handler被调用前正在执行(但马上就要发生替换)的那个new_handler函数。
对于malloc,客户并不能够去编程决定内存不足以分配时要干什么事,只能看着malloc返回NULL。
总结
将上面所述的10点差别整理成表格:
特征 | new/delete | malloc/free |
---|---|---|
分配内存的位置 | 自由存储区 | 堆 |
内存分配失败返回值 | 完整类型指针 | void* |
内存分配失败返回值 | 默认抛出异常 | 返回NULL |
分配内存的大小 | 由编译器根据类型计算得出 | 必须显式指定字节数 |
处理数组 | そこ] [新の新バージョンの配列を扱っています | ユーザー後のメモリ割り当ては、配列のサイズを計算する必要があります |
割り当てられた拡張メモリ | ない直感的な取り扱い | reallocを完全に使用するのは簡単 |
お互いを呼び出すするかどうか | あなたは、特定のオペレータが達成/新しい削除見ることができます | 新しい呼び出すことができません。 |
メモリ不足のメモリを割り当てるとき | お客様は、ハンドラまたはディストリビューターの再制定を指定することができます | ユーザーコードによって処理することができません |
関数のオーバーロード | 許します | 許可されていません |
コンストラクタとデストラクタ | コール | 呼び出さないでください |
malloc関数あなたは、生の土地の一部をしたいと思い、あなたは土地の種類を播種するまで所有する必要があります
新しい計画は、あなたがシード(コンストラクタ)を播種助けるために、良いブロック(配列)の土地を助けるために、またあなたの使用のための他の施設を提供しています。
もちろん、malloc関数は、該当する場合、新規として、彼らそれぞれが、持っていないと言うことではありません。C ++では、/削除、新規を使用してOOP言語でこの重点は、自然に、より適切です。
読んであなたの忍耐をありがとうございました。