void*operator new(std::size_t)throw(std::bad_alloc); void operator delete( void *) throw();该运算符在分配失败时将抛出异常,而非返回NULL。使用时要包含 <new>头文件。正常使用new,但要配以异常处理。如:
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(); } }2.nothrow new 不抛掷异常new
void*operator new(std::size_t,const std::nothrow_t & )throw(); void operator delete( void *) throw();该运算符在分配失败时不抛出异常,而是返回NULL。使用时要包含 <new>头文件。
>void*operator new(std::size_t ,void *); void operator delete( void * ,void *);该运算符是在已分配的内存上重新构造对象,因为不分配内存,所以不必担心分配失败。唯一的工作是调用构造函数。要包含 <new>头文件。
# 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仅仅是首址相同,所构建的对象可以类型不同。所“放置”的空间应小于原空间,以防不测。当”放置new”超过了申请的范围,Debug版下会挂机,但Release版竟然能运行而不出错!
# 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; //只释放空间,不再析构对象。 }注意:使用该运算符构造的对象或数组,一定要显式调用析构函数,不可用delete代替析构,因为placement new 的对象的大小不再与原空间相同。
# 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; // 错误 q-> ADT::~ADT(); //显式调用析构函数,仅释放对象 delete [ ]p; //最后,再用原指针来释放内存. }placement new 的主要用途就是可以反复使用一块已申请成功的内存空间。这样可以避免申请失败的徒劳,又可以避免使用后的释放。
特别要注意的是对于 placement new 绝不可以调用的delete, 因为该new只是使用别人替它申请的地方(只是个租房户,不是房主。无权将房子卖掉)。释放内存是nothrow new的事,即要使用原来的指针释放内存