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

C++ 侵入式智慧指標實作:引用計數基類與 Shared_Ptr 完整實現

     編輯:關於C++

侵入式 vs 非侵入式智慧指標

現代 C++ 中,shared_ptr 屬非侵入式:控制區塊(引用計數、刪除器)與被管理物件分離,智慧指標內部持有兩個指標。侵入式則將引用計數直接置於被管理類別內部(通常透過繼承基類),智慧指標僅持有單一物件指標。

非侵入式結構

侵入式結構

侵入式智慧指標設計要點

  1. 引用計數基類:封裝原子計數,需繼承此基類的類別才能被侵入式智慧指標管理。
  2. 模板化計數型別:預設使用原子計數(執行緒安全),可特化為 int(單執行緒、效能優先)。
  3. protected 建構/拷貝/解構:基類不可直接實例化,僅供繼承使用。
  4. 拷貝建構不複製計數:新物件計數歸零,因每個物件擁有獨立生命週期。
  5. 指派運算子不複製計數:A = B 僅拷貝資料成員,保留 A 原有計數。

引用計數基類實作

// 原子計數類別(簡化版,實際需含記憶體屏障)
class Atomic {
    volatile int _val;
public:
    Atomic(int v = 0) : _val(v) {}
    void inc_fast() { ++_val; }
    bool dec_and_test() { return --_val == 0; }
    int get() const { return _val; }
};

template<class T>
class HandleBaseT {
public:
    typedef T atomic_type;

    HandleBaseT& operator=(const HandleBaseT&) { return *this; } // 不拷貝計數

    void incRef() { _atomic.inc_fast(); }
    void decRef() {
        if (_atomic.dec_and_test() && !_bNoDelete) {
            _bNoDelete = true;
            delete this;
        }
    }
    int getRef() const { return _atomic.get(); }
    void setNoDelete(bool b) { _bNoDelete = b; }

protected:
    HandleBaseT() : _atomic(0), _bNoDelete(false) {}
    HandleBaseT(const HandleBaseT&) : _atomic(0), _bNoDelete(false) {} // 計數歸零
    virtual ~HandleBaseT() {}

    atomic_type _atomic;
    bool _bNoDelete;
};

// int 特化(非執行緒安全,效能較高)
template<> inline void HandleBaseT<int>::incRef() { ++_atomic; }
template<> inline void HandleBaseT<int>::decRef() {
    if (--_atomic == 0 && !_bNoDelete) { _bNoDelete = true; delete this; }
}
template<> inline int HandleBaseT<int>::getRef() const { return _atomic; }

// 預設使用 Atomic
typedef HandleBaseT<Atomic> HandleBase;

Shared_Ptr 智慧指標模板實作

struct Shared_PtrNull_Exception : public exception {
    Shared_PtrNull_Exception(const string& msg) : exception(msg.c_str()) {}
};

template<typename T>
class Shared_Ptr {
public:
    typedef T element_type;

    // 由原生指標建構
    Shared_Ptr(T* p = 0) : _ptr(p) { if (_ptr) _ptr->incRef(); }

    // 由其他型別 Shared_Ptr 建構(支援多型轉換)
    template<typename Y>
    Shared_Ptr(const Shared_Ptr<Y>& r) : _ptr(r._ptr) { if (_ptr) _ptr->incRef(); }

    // 拷貝建構
    Shared_Ptr(const Shared_Ptr& r) : _ptr(r._ptr) { if (_ptr) _ptr->incRef(); }

    ~Shared_Ptr() { if (_ptr) _ptr->decRef(); }

    // 指派:原生指標
    Shared_Ptr& operator=(T* p) {
        if (_ptr != p) {
            if (p) p->incRef();
            T* old = _ptr; _ptr = p;
            if (old) old->decRef();
        }
        return *this;
    }

    // 指派:其他型別 Shared_Ptr
    template<typename Y>
    Shared_Ptr& operator=(const Shared_Ptr<Y>& r) {
        if (_ptr != r._ptr) {
            if (r._ptr) r._ptr->incRef();
            T* old = _ptr; _ptr = r._ptr;
            if (old) old->decRef();
        }
        return *this;
    }

    // 指派:同型別 Shared_Ptr
    Shared_Ptr& operator=(const Shared_Ptr& r) {
        if (_ptr != r._ptr) {
            if (r._ptr) r._ptr->incRef();
            T* old = _ptr; _ptr = r._ptr;
            if (old) old->decRef();
        }
        return *this;
    }

    // 動態轉型輔助
    template<class Y> static Shared_Ptr dynamicCast(const Shared_Ptr<Y>& r) {
        return Shared_Ptr(dynamic_cast<T*>(r._ptr));
    }
    template<class Y> static Shared_Ptr dynamicCast(Y* p) {
        return Shared_Ptr(dynamic_cast<T*>(p));
    }

    T* get() const { return _ptr; }
    T* operator->() const { if (!_ptr) throw Shared_PtrNull_Exception("null handle"); return _ptr; }
    T& operator*() const { if (!_ptr) throw Shared_PtrNull_Exception("null handle"); return *_ptr; }
    operator bool() const { return _ptr != 0; }
    void swap(Shared_Ptr& other) { std::swap(_ptr, other._ptr); }

protected:
    void throwNullHandleException() const { throw Shared_PtrNull_Exception("shared_ptr null handle error"); }

public:
    T* _ptr;
};

// 比較運算子(支援置於 map 等容器)
template<typename T, typename U>
inline bool operator==(const Shared_Ptr<T>& lhs, const Shared_Ptr<U>& rhs) {
    T* l = lhs.get(); U* r = rhs.get();
    return (l && r) ? *l == *r : (!l && !r);
}
template<typename T, typename U>
inline bool operator!=(const Shared_Ptr<T>& lhs, const Shared_Ptr<U>& rhs) {
    T* l = lhs.get(); U* r = rhs.get();
    return (l && r) ? *l != *r : (l || r);
}
template<typename T, typename U>
inline bool operator<(const Shared_Ptr<T>& lhs, const Shared_Ptr<U>& rhs) {
    T* l = lhs.get(); U* r = rhs.get();
    return (l && r) ? *l < *r : (!l && r);
}

使用範例

class Test : public HandleBase {
    // 業務邏輯...
};

int main() {
    Shared_Ptr<Test> myTest = new Test(); // 自動管理引用計數
    myTest->doSomething();
    return 0;
}

此實作展示侵入式智慧指標的核心機制:基類封裝計數、智慧指標僅持有單一指標、支援多型轉換、執行緒安全(預設)。實際專案中可根據需求擴展自訂刪除器、弱引用等功能。

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