编写new和delete时的规则
既然是规则那就重点研究一下是什么规则:
例程:
1 void* operator new(std::size_t size) throw(std::bad_alloc){ 2 using namespace std; 3 if (size == 0) 4 size = 1; 5 while (true){ 6 尝试分配 size bytes; 7 if (分配成功) 8 return (一个指针 指向分配得来的内存); 9 10 //分配失败;找出目前的new-handling 11 new_handler globalHandler = set_new_handler(0); 12 set_new_handler(globalHandler); 13 14 if (globalHandler) (*globalHandler)(); 15 else throw std::bad_alloc(); 16 } 17 }
以上代码透露出一个标准的operator new应该做的几件事儿:
- 如果分配的字节大小是0,将其改为1.
- 里面包含一个死循环 出循环的条件是:
- 分配内存成功。
- 分配失败异常终止,抛出 bad_alloc的异常,这里之前侯捷老师的课里面有介绍,后面再看一遍来补充。
- set_new_handler 函数是在这里被运行的,关于运行set_new_handler 的意义之前说过,作为一个异常处理函数 主要有以下几件事儿需要做:
- 让更多的内存可用
- 安装另一个new_handler函数。
- 承认失败直接结束程序。
这里在运行异常处理函数的时候用了 (*globalHandler) (),用函数指针调用了该函数,在c++中,函数和函数指针之间的转换是可以的,可以不用*直接调用。
例程:
1 void ff(){ 2 std::cout << "runing me" << std::endl; 3 } 4 5 typedef void(*func_ptr)(); 6 int _tmain(int argc, _TCHAR* argv[]){ 7 8 func_ptr f_ptr = ff; 9 func_ptr f_ptr1 = &ff; 10 f_ptr(); 11 (*f_ptr)(); 12 f_ptr1(); 13 (*f_ptr1)(); 14 return 0; 15 }
运行结果:

议题二:重载new在继承体系中体现出的异常行为
1 class Base{ 2 public: 3 static void* operator new(std::size_t size) throw(std::bad_alloc); 4 ... 5 }; 6 class Derived : public Base{ ... }; 7 Derived* p = new Derived;
以上代码第7句执行的new操作将运行 base::operator new 这个函数可能引起内存分配异常,原因如下:
这个函数里面可能针对base做了一些特定的操作,但是这些特定的操作并不适合 Derived。
改进方式如下:
1 void* Base::operator new(std::size_t size) throw(std::bad_alloc){ 2 if (size != sizeof(Base)) 3 return ::new_handler(size); 4 ... 5 }
通过判断大小来确定待分配对象的具体大小再分别处理。这里成立的理由是 表达式 new将待分配对象的大小传给operator new 相当于operator new实际上是由表达式new在调用。
但是上面的方法对new[ ] 是行不通的,理由如下:
- 根据size参数无法判断分配数据类型,因为size大小由分配个数和类型共同决定。
- 传递给operator new的size_t参数,其值可能比可能比待分配的类型数组的大小要大,因为动态分配的arry operator需要额外的空间来存放元素个数等额外信息
议题三:重载operaor delete的规矩
规矩很简单:保证删除 空指针 NULL的安全性。
1 void operator delete(void* rawMemory) throw(){ 2 if (rawMemory == 0) return; 3 下面归还其它情况 4 }
简单的判断,区别对待。
关于这个内容有一个有意思的话题:当在继承体系中,而基类没有定义自己的虚析构函数是可能引发的异常:
这时,调用delete表达式传给 operator new的size可能是不对的,之前学过 delete 的两个步骤 先析构再 再operator delete 这里的大小是由delete来传递的。

浙公网安备 33010602011771号