這是在林銳的《高質(zhì)量程序設(shè)計(jì)指南》中看到的,特此記錄下。
1. plain new 普通new
- <span style="font-size: medium;">void*operator new(std::size_t)throw(std::bad_alloc);
- void operator delete( void *) throw();
- </span>
void*operator new(std::size_t)throw(std::bad_alloc);void operator delete( void *) throw();
該運(yùn)算符在分配失敗時(shí)將拋出異常,而非返回NULL。使用時(shí)要包含 <new>頭文件。正常使用new,但要配以異常處理。如:
- <span style="font-size: medium;">char *getMemory(unsigned long size)
- { char * p = new char[size];
- return p; }
- void main(void )
- { try{
- char * p = getMemory(1000000);
-
- delete [ ] p;
- }
- catch(const std::bad_alloc & ex)
- { cout < <ex.what(); }
- } </span>
char *getMemory(unsigned long size){ char * p = new char[size];return p; }void main(void ){ try{char * p = getMemory(1000000);//可能發(fā)生異常// ...delete [ ] p;}catch(const std::bad_alloc & ex){ cout < <ex.what(); }}
2.nothrow new 不拋擲異常new
- <span style="font-size: medium;">void*operator new(std::size_t,const std::nothrow_t & )throw();
- void operator delete( void *) throw(); </span>
void*operator new(std::size_t,const std::nothrow_t & )throw();void operator delete( void *) throw();
該運(yùn)算符在分配失敗時(shí)不拋出異常,而是返回NULL。使用時(shí)要包含 <new>頭文件。
該函數(shù)的第2形參是 struct nothrow_t { };它是個(gè)全局常對象 const nothrow_t nothrow; 用來作為 new 運(yùn)算符的標(biāo)志,以區(qū)別前一個(gè)new.
- <span style="font-size: medium;">void func(unsinged long length)
- {
- unsinged char * p = new(nothrow) unsinged char[length];
-
-
- if ( p == NULL)
- cout < <“allocte failed !”;
-
- delete [ ] p;
- } </span>
void func(unsinged long length){unsinged char * p = new(nothrow) unsinged char[length];//在使用這種new時(shí)要加(nothrow) ,明示不使用異常處理 。if ( p == NULL) // 因不拋異常,故定要檢查cout < <“allocte failed !”;// ...delete [ ] p;}
3.placement new 放置new
- <span style="font-size: medium;">void*operator new(std::size_t ,void *);
- void operator delete( void * ,void *); </span>
void*operator new(std::size_t ,void *);void operator delete( void * ,void *);
該運(yùn)算符是在已分配的內(nèi)存上重新構(gòu)造對象,因?yàn)椴环峙鋬?nèi)存,所以不必?fù)?dān)心分配失敗。唯一的工作是調(diào)用構(gòu)造函數(shù)。要包含 <new>頭文件。
- <span style="font-size: medium;"># include <new>
- # include <iostream>
- void main()
- { using namespace std;
- char * p = new(nothrow) char [4];
- if (p == NULL)
- { cout < <“allocte failed” < <endl; exit( -1 ); }
-
- long * q = new(p)long(1000);
- delete [ ]p;
- } </span>
# include <new># include <iostream>void main(){ using namespace std;char * p = new(nothrow) char [4];if (p == NULL){ cout < <“allocte failed” < <endl; exit( -1 ); }// ...long * q = new(p)long(1000);delete [ ]p; //只釋放 p,不要用q釋放。}
p和q僅僅是首址相同,所構(gòu)建的對象可以類型不同。所“放置”的空間應(yīng)小于原空間,以防不測。當(dāng)”放置new”超過了申請的范圍,Debug版下會掛機(jī),但Release版竟然能運(yùn)行而不出錯(cuò)!
該運(yùn)算符的作用是:只要第一次分配成功,不再擔(dān)心分配失敗。
- <span style="font-size: medium;"># include <new>
- # include <iostream>
- void main()
- { using namespace std;
- char * p = new(nothrow) char [100];
- if (p == NULL)
- { cout < <“allocte failed” < <endl; exit( -1 ); }
- long * q1 = new(p)long(100);
-
- int * q2 = new(p) int[100/sizeof(int) ];
-
- ADT * q3 = new(p) ADT[100/sizeof(ADT) ];
-
- delete [ ]p;
- } </span>
# include <new># include <iostream>void main(){ using namespace std;char * p = new(nothrow) char [100];if (p == NULL){ cout < <“allocte failed” < <endl; exit( -1 ); }long * q1 = new(p)long(100);// 使用q1 ...int * q2 = new(p) int[100/sizeof(int) ];// 使用q2 ...ADT * q3 = new(p) ADT[100/sizeof(ADT) ];// 使用q3 然后釋放對象 ...delete [ ]p; //只釋放空間,不再析構(gòu)對象。}
注意:使用該運(yùn)算符構(gòu)造的對象或數(shù)組,一定要顯式調(diào)用析構(gòu)函數(shù),不可用delete代替析構(gòu),因?yàn)閜lacement new 的對象的大小不再與原空間相同。
- <span style="font-size: medium;"># include <new>
- # include <iostream>
- void main()
- { using namespace std;
- char * p = new(nothrow) char [sizeof(ADT)+2];
- if (p == NULL)
- { cout < <“allocte failed” < <endl; exit( -1 ); }
-
- ADT * q = new(p) ADT;
-
-
- q-> ADT::~ADT();
- delete [ ]p;
- } </span>
# include <new># include <iostream>void main(){ using namespace std;char * p = new(nothrow) char [sizeof(ADT)+2];if (p == NULL){ cout < <“allocte failed” < <endl; exit( -1 ); }// ...ADT * q = new(p) ADT;// ...// delete q; // 錯(cuò)誤q-> ADT::~ADT(); //顯式調(diào)用析構(gòu)函數(shù),僅釋放對象delete [ ]p; //最后,再用原指針來釋放內(nèi)存.}
placement new 的主要用途就是可以反復(fù)使用一塊已申請成功的內(nèi)存空間。這樣可以避免申請失敗的徒勞,又可以避免使用后的釋放。
特別要注意的是對于 placement new 絕不可以調(diào)用的delete, 因?yàn)樵搉ew只是使用別人替它申請的地方(只是個(gè)租房戶,不是房主。無權(quán)將房子賣掉)。釋放內(nèi)存是nothrow new的事,即要使用原來的指針釋放內(nèi)存.