首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

Effective C++ 條款 51:遵循 new/delete 慣例——標準行為的完整實現指南

     編輯:關於C++

四大核心慣例

  1. operator new 失敗需循環嘗試、調用 new-handler、最終拋 bad_alloc。
  2. operator new 需處理 size == 0(返回合法非空指針)。
  3. operator delete 必須安全接受空指針(無操作)。
  4. 成員 new/delete 需處理繼承導致的 size > sizeof(Base) 情況。

全局 operator new 正確實現

void* operator new(std::size_t size) throw(std::bad_alloc) {
    if (size == 0) size = 1;               // 慣例 2
    while (true) {
        void* p = malloc(size);            // 嘗試分配
        if (p) return p;                   // 成功返回
        // 失敗:獲取並調用 new-handler
        std::new_handler handler = std::set_new_handler(0);
        std::set_new_handler(handler);
        if (handler) (*handler)();         // 嘗試釋放內存
        else throw std::bad_alloc();       // 無 handler 拋異常
    }
}

關鍵點:雙重 set_new_handler 實現「獲取當前 handler」(C++ 無直接獲取 API),多線程環境需加鎖。

類專屬 operator new(成員版)

用於特定類優化(如固定大小塊分配)。繼承陷阱:子類 new Derived 會調用 Base::operator new,但 size == sizeof(Derived)。

class Base {
public:
    static void* operator new(std::size_t size) throw(std::bad_alloc) {
        if (size != sizeof(Base))          // 慣例 4:非本類大小轉發全局
            return ::operator new(size);
        // 專屬分配邏輯...
    }
    static void operator delete(void* p, std::size_t size) throw() {
        if (p == 0) return;                // 慣例 3
        if (size != sizeof(Base)) {
            ::operator delete(p);          // 轉發全局 delete
            return;
        }
        // 專屬釋放邏輯...
    }
};

注意:size == 0 無需檢查,因獨立對象最小 1 字節(空類插入 char),sizeof(Base) > 0 恆成立。

operator new[] / delete[] 特殊性

  • 參數 size 可能大於元素總大小(編譯器可能存儲數組大小/對齊填充)。
  • 不可假設元素個數或逐個構造/析構——交由編譯器生成的代碼處理。

虛析構函數的關鍵作用

Base* p = new Derived;
delete p; // 若 Base::~Base() 非 virtual,傳入 delete 的 size = sizeof(Base) → 錯誤釋放!
// 若 virtual,size = sizeof(Derived) → 正確

這正是條款 7 強調「基類析構函數必須虛化」的底層原因之一。

總結清單

函數必須處理返回/行為
global newsize=0, 失敗循環+handler非空指針或拋 bad_alloc
global delete空指針無操作返回
member newsize != sizeof(Class) 轉發同 global
member delete空指針、size != sizeof(Class) 轉發同 global
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved