裸指標 new/delete 易導致記憶體洩漏 (異常跳過 delete)、二次釋放、懸空指標。智慧指標以RAII (Resource Acquisition Is Initialization) 封裝指標,建構時獲取資源,解構時自動釋放,保證異常安全。
擁有權轉移 語意:拷貝/指派會將來源指標置空,目的地接管擁有權。
auto_ptrp1(new Foo); auto_ptr p2 = p1; // p1 變空,p2 擁有 // 缺點:不可放入 STL 容器、不可共享擁有權、const 不正確
獨占擁有權,不可複製、不可移動 (私有拷貝建構/指派)。適合單一作用域內的獨佔資源。
scoped_ptrp(new Foo); // 無拷貝、無指派 // 現代替代:std::unique_ptr
獨占擁有權,可移動、不可複製。零開銷抽象,支援陣列 unique_ptr、自定義刪除器、轉換 shared_ptr。
unique_ptrp1 = make_unique (); unique_ptr p2 = move(p1); // 移動轉移擁有權 // 首選獨占資源管理工具
共享擁有權,引用計數。控制區塊儲存強引用計數、弱引用計數、刪除器、配置器。make_shared 單次配置物件+控制區塊。
auto p1 = make_shared(); auto p2 = p1; // 計數+1 // 計數歸零時 delete
非擁有權觀察者,不增加強引用計數。必須 lock() 取得 shared_ptr 才能存取。解決 shared_ptr 循環引用 (雙向鏈表、父子雙向、觀察者模式、快取)。
struct Node { shared_ptr next; weak_ptr prev; };
// prev 不增加計數,打破循環
struct Node {
int data;
shared_ptr next;
weak_ptr prev; // 弱引用打破循環
};
void test() {
auto a = make_shared();
auto b = make_shared();
a->next = b;
b->prev = a; // weak_ptr,計數維持 1
} // 正常釋放

管理非 new 資源:
// FILE* shared_ptrfp(fopen("f.txt","w"), fclose); // malloc shared_ptr buf(malloc(100), free); // C 陣列 shared_ptr arr(new int[10], [](int* p){ delete[] p; }); // Windows HANDLE shared_ptr h(CreateFile(...), [](void* h){ CloseHandle(h); });
templateclass SharedPtr { T* ptr; int* count; // 強引用計數 public: SharedPtr(T* p = nullptr) : ptr(p), count(p ? new int(1) : nullptr) {} ~SharedPtr() { dec(); } SharedPtr(const SharedPtr& rhs) : ptr(rhs.ptr), count(rhs.count) { inc(); } SharedPtr& operator=(const SharedPtr& rhs) { if (this != &rhs) { dec(); ptr = rhs.ptr; count = rhs.count; inc(); } return *this; } T& operator*() const { return *ptr; } T* operator->() const { return ptr; } int use_count() const { return count ? *count : 0; } private: void inc() { if (count) ++*count; } void dec() { if (count && --*count == 0) { delete ptr; delete count; } } };
make_unique / make_shared:例外安全、效能優化。unique_ptr,參數傳遞用 unique_ptr& 或 T* (觀察者)。shared_ptr,觀察者/打破循環用 weak_ptr。shared_ptr 管理 this (需 enable_shared_from_this)。shared_ptr 型別一部分,勿混用。unique_ptr 或 shared_ptr(new T[n], [](T* p){delete[] p;}) 。weak_ptr。