4. new和delete
C++内存分配时一种类型化操作:new为特定类型分配内存,并在新分配的内存中构造对象。new表达式自行运行合适的构造函数来初始化每个动态分配的类类型对象。
首先需要对new和delete表达式怎样工作有更多的理解。当使用new表达式
string* sp = new string("initialized")
的时候,实际上发生了三个步骤。首先,该表达式调用名为operator new的标准库函数,分配足够大的原始的未类型化的内存,以保存指定类型的一个对象;接下来,运行该类型的一个构造函数,用指定初始化构造对象;最后,返回指向新分配并构造的对象的指针。
delete sp;
当使用delete表达式delete sp;删除动态分配对象的时候,发生两个步骤。首先,对sp指向的对象运行适当的析构函数;然后调用operator delete的标准库函数释放该对象所用内存。
5. 了解new-handler的行为
当operator new无法满足某一内存分配需求时,它会抛出异常。以前它会返回一个null指针,某些旧式编译器目前也还那么做。你还是可以取得旧行为。
当operator new抛出异常以反映一个未获满足的内存需求之前,它会先调用一个客户指定的错误处理函数,一个所谓的new-handler。为了指定这个“用以处理内存不足”的函数,客户必须调用set_new_handler,那么声明于<new>的标准程序库函数:
<span style="font-size:12px;">namespace std{ typedef void (* new_handler)(); new_handler set_new_handler(new_handler p) throw(); }</span> |
new_handler是应该以无输入无返回的函数指针。
<span style="font-size:12px;">void * operator new(std::size_t size) throw(std::bad_alloc){ using namespace std; if(size==0) size=1; while(true){ 尝试分配size byte; if(success) return a pointor; //if failed new_handler globalHandler=set_new_handler(0); //获取当前的new_handler set_new_handler(globalHandler); if(globalHandler) (*globalHandler)(); else throw std::bad_alloc(); } }</span> |
一个良好设计的new-handler函数必须做以下事情:
让更多的内存可以被使用。这便造成operator new内的下一次内存分配动作可能成功。
安装另一个new-handler。如果目前这个new-handler无法取得更多可用内存,或者它知道另外哪个new-handler有此能力。果真如此,目前这个new-handler就可以安装另外那个new-operator以替换自己(调用set_new_handler)。
卸除new-handler,就是将null指针传给set_new_handler。一旦没有安装任何new_handler, operator new会在内存分配不成功时抛出异常。
抛出bad_alloc(或派生自bad_alloc)的异常。
不返回,通常调用abort或exit