C++進階--解謎operator new/delete
阿新 • • 發佈:2018-12-26
//############################################################################ // 解謎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庫 */