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

C++ 智能指針進階:unique_ptr/shared_ptr 構造差異、刪除器、第三方內存管理

     編輯:C++ 入門

C++ 智能指針進階:unique_ptr/shared_ptr 構造差異、刪除器、第三方內存管理

智能指針是現代 C++ 資源管理核心。本文聚焦實踐中易忽視的細節:動態數組支持、刪除器類型擦除、Lambda 捕獲陷阱、第三方庫內存托管模式。

1. 動態數組支持差異

  • unique_ptr:原生支持 unique_ptr<T[]> p(new T[n]),析構自動 delete[]。
  • shared_ptr:不支持 shared_ptr<T[]>(C++17 前)。需自定義刪除器:
// 正確寫法
shared_ptr p(new int[10], [](int* ptr){ delete[] ptr; });
// 或使用 default_delete
shared_ptr p(new int[10], default_delete());
// 封裝工廠函數
template
shared_ptr make_shared_array(size_t n) {
    return shared_ptr(new T[n], default_delete());
}

2. 刪除器指定方式差異

shared_ptrunique_ptr
語法構造函數第 2 參數模板第 2 參數(類型)
Lambda 無捕獲自動推導可轉函數指針 void(*)(T*)
Lambda 有捕獲自動推導不可轉函數指針,需用 function<void(T*)>
// unique_ptr 指定帶捕獲 Lambda 的刪除器
unique_ptr> p(new int(1), [&](int* ptr){ delete ptr; log(); });
// 自定義刪除器結構體
struct MyDeleter { void operator()(int* p) { cout<<"del"; delete p; } };
unique_ptr p(new int(1));

3. 管理第三方庫分配的內存

場景:第三方庫提供 Create()/Release(),必須配對調用,否則洩漏。智能指針通過自定義刪除器完美解決:

void* handle = Lib::Create();
// 危險:手動管理
// Lib::Release(handle);

// 安全:shared_ptr 托管
shared_ptr guard(handle, [](void* p){ Lib::Release(p); });
// 甚至封裝宏避免忘記賦值
#define GUARD(ptr) shared_ptr ptr##_guard(ptr, [](void* p){ Lib::Release(p); })
// 使用
void* p = Lib::Create();
GUARD(p); // 編譯期強制綁定變量名,防止臨時對象提前釋放

4. unique_ptr 版第三方托管

#define GUARD(ptr) unique_ptr ptr##_guard(ptr, [](void* p){ Lib::Release(p); })

注意:Lambda 無捕獲才能轉函數指針;有捕獲需用 function 但 unique_ptr 模板參數需完整類型,較繁瑣。

5. C++14/17/20 新特性

  • C++14:make_unique(單對象),數組版 make_unique<T[]>(n)。
  • C++17:shared_ptr 支持數組 shared_ptr<T[]>,自動 delete[]。
  • C++20:std::atomic<shared_ptr> 原子操作。

6. 核心原理回顧

  • shared_ptr:控制塊包含強引用計數、弱引用計數、刪除器、分配器。線程安全引用計數(原子操作),但指向對象訪問不安全。
  • unique_ptr:零開銷(單指針大小),獨占所有權,移動語義轉移。刪除器類型為模板參數,不佔用對象空間(EBO 優化)。

善用智能指針能消滅 90% 內存洩漏。關鍵在於:理解所有權語義、正確指定刪除器、封裝第三方資源為 RAII 類型。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved