猫猫哥

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
//############################################################################
// 解谜operator new/delete

/* 执行下面代码会发生什么? 
 */

   dog* pd = new dog();
/* 
 * Step 1. 调用operator new分配内存
 * Step 2. 调用构造函数构造dog
 * Step 3. 如果第2部抛异常,调用operator delete释放第1步分配的内存 
 */
   delete pd;
/* 
 * Step 1. 调用dog的析构函数
 * Step 2. 调用operator delete释放内存
 */


/*
 * 自己实现operator new:
 *
 * 注意: new handler是当operator new分配内存失败时调用的函数
 *   set_new_handler()函数设置一个新的new handler并且返回当前的new handler
 */
void* operator new(std::size_t size) throw(std::bad_alloc) {
   while (true) {
      void* pMem = malloc(size);   // 分配内存
      if (pMem) 
         return pMem;              // 成功则返回指针

      std::new_handler Handler = std::set_new_handler(0);  // 获取当前的new handler
      std::set_new_handler(Handler);  //写回

      if (Handler)
         (*Handler)();            // 调用new handler
      else
         throw bad_alloc();       // 如果new handler为空, 抛异常
   }
}


/* 
 * 成员函数中的Operator new
 */
class dog {
   ...
   public:
   static void* operator new(std::size_t size) throw(std::bad_alloc) 
   {
//      if (size == sizeof(dog))
         customNewForDog(size);
 //     else
//         ::operator new(size);
   }
   ...
};

class yellowdog : public dog {
   int age;
   static void* operator new(std::size_t size) throw(std::bad_alloc) 
};

int main() {
   yellowdog* py= new yellowdog();   //调用了dog的operator new
}

/*
* 解决方法 1:
*     if (size == sizeof(dog))  //加判断
*        customNewForDog();
*     else
*        return ::operator new(size);
*
* 解决方法 2:
*     yellowdog也重载operator new
*/



/* operator delete也是类似 */
class dog {
   static void operator delete(void* pMemory) throw() {  //
      cout << "Bo is deleting a dog, \n";
      customDeleteForDog();
      free(pMemory);
   }
//   virtual ~dog() {};   
};

class yellowdog : public dog {
   static void operator delete(void* pMemory) throw() {
      cout << "Bo is deleting a yellowdog, \n";
      customDeleteForYellowDog();
      free(pMemory);
   }
};

int main() {
   dog* pd = new yellowdog();
   delete pd;   //调用了dog的operator delete
}

// 如何解决?
// operator delete定义成虚函数?
// 不行!不能既是静态函数(对象无关)又是虚函数(对象相关)
//
//
// 解决方法:
//   virtual ~dog() {}
// 为什么加个虚析构函数就ok?
// 先调析构(多态),再释放内存





/*
 * 为什么要自定义new/delete
 *
 * 1. 使用错误检测: 
 *    - 内存泄漏检测/垃圾回收. 
 *    - 数组的索引超出范围,在内存的首尾做签名,就可以检测数组越界
 * 2. 提升效率:
 *    a. 将相关对象聚类,减少页错误(不命中)
 *    b. 固定大小分配(适合很多小对象的应用)
 *    c. 将相似尺寸的对象排到同一位置以减小碎片
 * 3. 执行额外的任务:
 *    a. 将去分配的内存清0--安全性.
 *    b. 收集使用统计
 */

/*
 * 写一个好的内存管理器很难!
 *
 * 在写自己版本的之前, 考虑:
 *
 * 1. 根据你的需要调教下你的编译器;
 * 2. 搜索内存管理库, 例如boost中的pool库
 */
posted on 2018-12-26 22:51  猫猫哥  阅读(242)  评论(0编辑  收藏  举报