| 維度 | C 風格 | C++ 風格 |
|---|---|---|
| 分配/釋放 | malloc/free |
new/delete、new[]/delete[] |
| 建構/解構 | 無(僅原始記憶體) | 自動呼叫建構函數與解構函數 |
| 失敗處理 | 回傳 NULL |
拋出 std::bad_alloc 異常(可用 nothrow 版本回傳 NULL) |
| 型別安全 | 需強制轉型 | 編譯期型別檢查 |
手動 new/delete 易因異常、提前 return、複雜流程導致記憶體洩漏:
{
int* p = new int(5);
// ... 複雜邏輯 ...
if (error) throw MyException(); // 此處洩漏!
delete p;
}
智慧指標採用 RAII(Resource Acquisition Is Initialization):物件建構時獲取資源,離開作用域時自動釋放,無論正常返回或異常拋出皆安全。
| 類型 | 所有權語義 | 複製行為 | 適用場景 |
|---|---|---|---|
auto_ptr (C++98, C++11 棄用) |
獨占,複製即轉移 | 複製後來源歸零 | 已淘汰,易在演算法(如 sort)中導致邏輯錯誤 |
scoped_ptr (Boost) |
獨占,不可複製 | 編譯期禁止複製/賦值 | 單一作用域內獨占資源,無轉移需求 |
shared_ptr (C++11) |
共享,引用計數 | 複製增加計數 | 多處共享同一資源,生命週期由最後持有者決定 |
weak_ptr (C++11) |
弱引用,不增加計數 | 可複製,不影響生命週期 | 打破 shared_ptr 循環引用(雙向鏈表、觀察者模式) |
unique_ptr (C++11) |
獨占,可移動 | 禁止複製,支援移動語義 | 現代 C++ 首選獨占智慧指標,零開銷 |
template <class T>
class ScopedPtr {
T* _ptr;
public:
explicit ScopedPtr(T* ptr = nullptr) : _ptr(ptr) {}
~ScopedPtr() { delete _ptr; }
T& operator*() { return *_ptr; }
T* operator->() { return _ptr; }
private:
ScopedPtr(const ScopedPtr&); // 禁止複製
ScopedPtr& operator=(const ScopedPtr&); // 禁止賦值
};
編譯器優化 operator->:ptr->member 直接轉為 ptr.operator->()->member。
控制區塊包含:強引用計數、弱引用計數、刪除器、分配器。拷貝構造/賦值時原子增減強引用計數,歸零時呼叫刪除器。
// 父節點 shared_ptr 持有子節點,子節點 weak_ptr 持有父節點
struct Node {
shared_ptr<Node> child;
weak_ptr<Node> parent; // 不增加計數
};
lock() 可嘗試提升為 shared_ptr(若物件尚存活)。
explicit,必須 shared_ptr<int> p(new int(1))return make_shared<T>() 或 shared_ptr<T> tmp(...); return tmp;get() 取得原始指標後 delete:導致雙重釋放make_shared:單次分配物件+控制區塊,效率更高、異常安全shared_ptr 管理陣列:C++17 前無 delete[] 支援,改用 unique_ptr<T[]> 或 vectorunique_ptr(獨占)+ shared_ptr/weak_ptr(共享)weak_ptr 斷環