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

C++ 智能指針深度解析:auto_ptr 缺陷與 shared_ptr 參考計數實現

     編輯:關於C++

auto_ptr:被棄用的先驅

auto_ptr(C++98)嘗試實現獨占所有權語義,但複製/賦值會轉移所有權,導致嚴重缺陷:

  • 放入標準容器(如 vector>)會導致元素變為空指針。
  • 無法正確管理數組(delete vs delete[])。
  • 不支持共享所有權。

C++11 棄用,C++17 移除。請勿在新代碼中使用。

auto_ptr 核心實現(理解歷史教訓)

template
class auto_ptr {
    T* ptr;
public:
    explicit auto_ptr(T* p = nullptr) : ptr(p) {}
    ~auto_ptr() { delete ptr; }
    
    // 複製構造:轉移所有權
    auto_ptr(auto_ptr& other) : ptr(other.release()) {}
    auto_ptr& operator=(auto_ptr& other) {
        if (this != &other) reset(other.release());
        return *this;
    }
    
    T& operator*() const { return *ptr; }
    T* operator->() const { return ptr; }
    T* get() const { return ptr; }
    T* release() { T* old = ptr; ptr = nullptr; return old; }
    void reset(T* p = nullptr) { if (ptr != p) { delete ptr; ptr = p; } }
};

shared_ptr:共享所有權的標準解法

核心機制:引用計數。多個 shared_ptr 共享同一控制塊,計數歸零時釋放資源。

內部結構

  • 存儲指針:指向對象(T*)。
  • 控制塊指針:指向控制塊,包含:
    - 強引用計數(shared_ptr 數量)
    - 弱引用計數(weak_ptr 數量)
    - 刪除器(deleter)
    - 分配器(allocator)

線程安全

  • 控制塊的引用計數增減是原子操作(線程安全)。
  • 但對象本身的訪問不保證線程安全,需外部同步。
  • 多線程同時讀取同一 shared_ptr 安全;同時寫入(賦值/重置/銷毀)同一 shared_ptr 不安全,需加鎖。

shared_ptr 關鍵操作

shared_ptr p1(new T);          // 計數=1
shared_ptr p2 = p1;            // 計數=2
shared_ptr p3;
p3 = p1;                          // 計數=3
p1.reset();                       // 計數=2
p2.reset();                       // 計數=1
p3.reset();                       // 計數=0 → 釋放對象

// make_shared:單次分配對象+控制塊,效率更高
auto p = make_shared(args...);

// 獲取裸指針(慎用)
T* raw = p.get();

// 自定義刪除器
shared_ptr p(new T, [](T* ptr){ /* custom delete */ });

shared_ptr vs unique_ptr vs weak_ptr

指針類型所有權複製語義典型用途
unique_ptr獨占移動語義(不可複製)獨占資源、RAII、工廠返回
shared_ptr共享複製增加計數多對象共享、緩存、觀察者模式
weak_ptr弱引用(不增加強計數)可複製打破循環引用、緩存、觀察者

常見陷阱

  1. 循環引用:A 持有 B 的 shared_ptr,B 持有 A 的 shared_ptr → 永不釋放。解決:一方用 weak_ptr。
  2. 混用裸指針:shared_ptr p1(new T); shared_ptr p2(p1.get()); → 雙重釋放。永不從裸指針構造多個 shared_ptr。
  3. 數組管理:shared_ptr (C++17) 或自定義刪除器 shared_ptr(new T[n], default_delete())。
  4. this 指針構造 shared_ptr:繼承 enable_shared_from_this,用 shared_from_this()。

總結

auto_ptr 是歷史教訓:複製即轉移所有權 破壞了值語義。
shared_ptr 通過引用計數 + 控制塊 正確實現共享所有權,是現代 C++ 共享資源管理的標準工具。
最佳實踐:優先用 unique_ptr 表達獨占,需共享時用 shared_ptr,打破循環用 weak_ptr,永遠用 make_shared/make_unique 構造。

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