C++簡(jiǎn)單實(shí)現(xiàn)shared_ptr的代碼
一、一些說(shuō)明
1.智能指針用于資源管理,為了保證資源的操作得到順利的執(zhí)行防止資源泄露,因此大多數(shù)實(shí)現(xiàn)都以noexcept在參數(shù)列表后聲明為不拋出異常。
2.對(duì)于有些明確不需要更改調(diào)用對(duì)象內(nèi)容的成員函數(shù),用const在參數(shù)列表后修飾,常量成員函數(shù)不能改變調(diào)用它的對(duì)象的內(nèi)容。
3.在用原始指針構(gòu)造智能指針的參數(shù)構(gòu)造前用explicit聲明,防止隱式的轉(zhuǎn)化。
3.swap函數(shù)內(nèi)部調(diào)用標(biāo)準(zhǔn)命名空間的swap()函數(shù),必須以std::顯示指定是標(biāo)準(zhǔn)命名空間
4.做筆記使用,如果有不足或者錯(cuò)誤的地方還請(qǐng)補(bǔ)充或者指正?。《嘀x?。?!
二、基本的構(gòu)造和析構(gòu)成分
SharedPtr()noexcept = default // 默認(rèn)構(gòu)造 explicit SharedPtr(T* ptr) noexcept // 參數(shù)構(gòu)造 SharedPtr(const SharedPtr& ptr)noexcept // 拷貝構(gòu)造 SharedPtr(SharedPtr&& ptr)noexcept // 移動(dòng)構(gòu)造 ~SharedPtr() noexcept // 析構(gòu)函數(shù)
三、運(yùn)算符重載
SharedPtr& operator=(const SharedPtr& rhs)noexcept // 拷貝賦值運(yùn)算符重載 SharedPtr& operator=(SharedPtr&& rhs)noexcept // 移動(dòng)賦值運(yùn)算符重載 T& operator->() const noexcept // 指針運(yùn)算符重載 T& operator*() const noexcept // 解引用運(yùn)算符重載
四、實(shí)現(xiàn)的shared_ptr函數(shù)接口
T* get() const noexcept // 獲取原始指針對(duì)象 int use_count() const noexcept // 獲取引用計(jì)數(shù) void reset()noexcept // 重置指針 bool unique() noexcept // 判斷是否只有一個(gè)使用者 void swap() noexcept // 交換對(duì)象內(nèi)容
五、CPP代碼
#include<iostream> using namespace std; // 引用計(jì)數(shù)類(lèi) class RefCount { private: int count{1}; public: int use_count() const noexcept { return count; } void dec_count()noexcept { --count; } void inc_count()noexcept { ++count; } }; // shared_ptr類(lèi)模板 template<class T> class SharedPtr { private: T* origin_ptr{ nullptr }; // 原始指針 RefCount* refCount{ nullptr }; // 引用計(jì)數(shù) public: SharedPtr()noexcept = default; // 默認(rèn)構(gòu)造 SharedPtr(nullptr_t)noexcept :SharedPtr() {} // 空指針構(gòu)造 explicit SharedPtr(T* ptr)noexcept :origin_ptr(ptr), refCount(nullptr){ // 用原始指針作為參數(shù)構(gòu)造 if (origin_ptr != nullptr) refCount = new RefCount(); } SharedPtr(const SharedPtr& ptr)noexcept :origin_ptr(ptr.origin_ptr), refCount(ptr.refCount) { // 拷貝構(gòu)造 if(origin_ptr != nullptr) refCount->inc_count(); } SharedPtr(SharedPtr&& ptr)noexcept :origin_ptr(ptr.origin_ptr), refCount(ptr.refCount) { // 移動(dòng)構(gòu)造 ptr.origin_ptr = nullptr; ptr.refCount = nullptr; } ~SharedPtr()noexcept { // 析構(gòu)函數(shù) if (origin_ptr != nullptr && refCount->use_count() == 0) { delete origin_ptr; delete refCount; origin_ptr = nullptr; refCount = nullptr; } } SharedPtr& operator=(const SharedPtr& rhs)noexcept { // 拷貝賦值運(yùn)算符重載 SharedPtr(rhs).swap(*this); return *this; } SharedPtr& operator=(SharedPtr&& rhs)noexcept { // 移動(dòng)賦值運(yùn)算符重載 SharedPtr(move(rhs)).swap(*this); return *this; } T& operator->() const noexcept{ // 指針運(yùn)算符重載 return origin_ptr; } T& operator*() const noexcept { // 解引用運(yùn)算符重載 return *origin_ptr; } public: // 以下是提供的接口函數(shù) T* get()const noexcept { // get()函數(shù)獲取原始指針對(duì)象 return origin_ptr; } int use_count() const noexcept { // use_count()函數(shù)獲取引用計(jì)數(shù) return origin_ptr == nullptr ? 0 : refCount->use_count(); } void reset()noexcept { // reset()重置指針 SharedPtr().swap(*this); } void reset(nullptr_t) noexcept { reset(); } void reset(T* ptr)noexcept { SharedPtr(ptr).swap(*this); } bool unique()noexcept { // unique() 查看是否資源獨(dú)有 return refCount == nullptr ? false : (refCount->use_count() == 1); } void swap(SharedPtr& rhs) noexcept{ // swap()交換對(duì)象內(nèi)容 std::swap(origin_ptr, rhs.origin_ptr); // 這里必須顯示指定是std命名空間! std::swap(refCount, rhs.refCount); } }; int main() { int* a = new int(2); SharedPtr<int>p(a); //測(cè)試構(gòu)造函數(shù) cout << p.use_count() << endl; cout << *p << endl; SharedPtr<int>q(p); //測(cè)試拷貝構(gòu)造 cout << p.use_count() << endl; cout << q.use_count() << endl; SharedPtr<int>n = p; //測(cè)試賦值運(yùn)算符 cout << p.use_count() << endl; cout << n.use_count() << endl; SharedPtr<int>m = move(p); //測(cè)試右值引用賦值運(yùn)算符 cout << q.use_count() << endl; // cout << p.get_count() << endl; q.reset(); cout << q.get() << endl; return 0; }
C++ 簡(jiǎn)單實(shí)現(xiàn)shared_ptr
共享指針
管理指針的存儲(chǔ),提供有限的垃圾回收工具,并可能與其他對(duì)象共享該管理。
shared_ptr類(lèi)型的對(duì)象都能夠獲得指針的所有權(quán)并共享該所有權(quán):一旦它們獲得所有權(quán),當(dāng)最后一個(gè)所有者釋放該所有權(quán)時(shí),指針的所有者組就負(fù)責(zé)刪除該所有者。
shared_ptr對(duì)象在自身被銷(xiāo)毀后,或者一旦其值因賦值操作或顯式調(diào)用 shared_ptr::reset 而發(fā)生更改,就會(huì)釋放其共同擁有的對(duì)象的所有權(quán)。一旦通過(guò)指針共享所有權(quán)的所有shared_ptr對(duì)象都釋放了此所有權(quán),則將刪除托管對(duì)象(通常通過(guò)調(diào)用 ::delete,但在構(gòu)造時(shí)可能會(huì)指定不同的刪除程序)。
shared_ptr對(duì)象只能通過(guò)復(fù)制其值來(lái)共享所有權(quán):如果從同一個(gè)(非shared_ptr)指針構(gòu)造(或創(chuàng)建)兩個(gè)shared_ptr,則它們都將擁有該指針而不共享它,當(dāng)其中一個(gè)對(duì)象釋放它(刪除其托管對(duì)象)并使另一個(gè)指向無(wú)效位置時(shí),會(huì)導(dǎo)致潛在的訪(fǎng)問(wèn)問(wèn)題。
此外,shared_ptr對(duì)象可以通過(guò)指針共享所有權(quán),同時(shí)指向另一個(gè)對(duì)象。此功能稱(chēng)為別名,通常用于指向成員對(duì)象,同時(shí)擁有它們所屬的對(duì)象。因此,shared_ptr可能與兩個(gè)指針相關(guān):
- 存儲(chǔ)的指針,它是它所指向的指針,也是它使用運(yùn)算符* 取消引用的指針。
- 擁有的指針(可能是共享的),這是所有權(quán)組負(fù)責(zé)在某個(gè)時(shí)刻刪除的指針,并且它被視為一種用途。
通常,存儲(chǔ)的指針和擁有的指針引用同一對(duì)象,但別名shared_ptr對(duì)象(使用別名構(gòu)造函數(shù)及其副本構(gòu)造的對(duì)象)可能引用不同的對(duì)象。
不擁有任何指針的shared_ptr稱(chēng)為空shared_ptr。不指向任何對(duì)象的shared_ptr稱(chēng)為 null shared_ptr,不應(yīng)取消引用。請(qǐng)注意,空shared_ptr不一定是 null shared_ptr,null shared_ptr不一定是空shared_ptr。
shared_ptr對(duì)象通過(guò)運(yùn)算符 * 和 -> 提供對(duì)它們所指向的對(duì)象的訪(fǎng)問(wèn),從而復(fù)制有限的指針功能。出于安全原因,它們不支持指針?biāo)阈g(shù)。
相關(guān)類(lèi)weak_ptr能夠與shared_ptr對(duì)象共享指針,而無(wú)需擁有它們。
成員函數(shù)
(構(gòu)造函數(shù))構(gòu)造shared_ptr(公共成員函數(shù)) (析構(gòu)函數(shù))銷(xiāo)毀shared_ptr(公共成員函數(shù)) operator= shared_ptr賦值(公共成員函數(shù)) swap 交換內(nèi)容(公共成員函數(shù)) reset 重置指針(公共成員函數(shù)) get 獲取指針(公共成員函數(shù)) operator* 取消引用對(duì)象(公共成員函數(shù)) operator-> 取消引用對(duì)象成員(公共成員函數(shù)) operator[] (C++17)提供到被存儲(chǔ)數(shù)組的帶下標(biāo)訪(fǎng)問(wèn)(公開(kāi)成員函數(shù)) use_count 返回計(jì)數(shù)(公共成員函數(shù)) unique(C++20前) 檢查是否唯一(公共成員函數(shù)) operator bool 檢查是否不為空(公共成員函數(shù)) owner_before 基于所有者的共享指針排序(公共成員函數(shù)模板) 非成員函數(shù) swap 交換shared_ptr對(duì)象的內(nèi)容(函數(shù)模板) relational operators 關(guān)系運(yùn)算符 ==, !=, <, <=, >, >= (函數(shù)模板 ) ostream operator<< 將存儲(chǔ)的指針的值輸出到輸出流(函數(shù)模板) 具體功能: make_shared,make_shared_for_overwrite(C++20) 創(chuàng)建管理一個(gè)新對(duì)象的共享指針(函數(shù)模板) allocate_shared,allocate_shared_for_overwrite(C++20) 創(chuàng)建管理一個(gè)用分配器分配的新對(duì)象的共享指針(函數(shù)模板) static_pointer_cast,dynamic_pointer_cast,const_pointer_cast,reinterpret_pointer_cast (C++17)應(yīng)用 static_cast、dynamic_cast、const_cast 或 reinterpret_cast 到被存儲(chǔ)指針(函數(shù)模板) get_deleter 返回指定類(lèi)型中的刪除器,若其擁有(函數(shù)模板)
cpp
#include <utility> #include <cstddef> class ref_count { public: int use_count() const noexcept { return count_; } void inc_ref() noexcept { ++count_; } int dec_ref() noexcept { return --count_; } private: int count_{1}; }; template <typename T> class Shared_ptr { public: constexpr Shared_ptr() noexcept = default; constexpr Shared_ptr(nullptr_t) noexcept : Shared_ptr() {} explicit Shared_ptr(T *ptr) : ptr_{ptr} { if (ptr_ != nullptr) { rep_ = new ref_count{}; } } Shared_ptr(const Shared_ptr &rhs) noexcept : ptr_{rhs.ptr_}, rep_{rhs.rep_} { if (ptr_ != nullptr) { rep_->inc_ref(); } } Shared_ptr(Shared_ptr &&rhs) noexcept : ptr_{rhs.ptr_}, rep_{rhs.rep_} { rhs.ptr_ = nullptr; rhs.rep_ = nullptr; } ~Shared_ptr() noexcept { if (rep_ != nullptr && rep_->dec_ref() == 0) { delete ptr_; delete rep_; } } Shared_ptr &operator=(const Shared_ptr &rhs) { Shared_ptr{rhs}.swap(*this); return *this; } Shared_ptr &operator=(Shared_ptr &&rhs) { Shared_ptr{std::move(rhs)}.swap(*this); return *this; } void reset() noexcept { Shared_ptr{}.swap(*this); } void reset(nullptr_t) noexcept { reset(); } void reset(T *ptr) { Shared_ptr{ptr}.swap(*this); } void swap(Shared_ptr &rhs) noexcept { std::swap(ptr_, rhs.ptr_); std::swap(rep_, rhs.rep_); } T *get() const noexcept { return ptr_; } long use_count() const noexcept { return rep_ == nullptr ? 0 : rep_->use_count(); } bool unique() const noexcept { return rep_->use_count() == 1; } T &operator*() const noexcept { return *ptr_; } T &operator->() const noexcept { return ptr_; } explicit operator bool() const noexcept { return static_cast<bool>(ptr_); } private: T *ptr_{nullptr}; ref_count *rep_{nullptr}; }; template <typename T, typename... Args> auto make_Shared(Args &&...args) { return Shared_ptr<T>{new T(std::forward(args)...)}; }
到此這篇關(guān)于C++ shared_ptr實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)C++ shared_ptr實(shí)現(xiàn)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- C++特性之智能指針shared_ptr詳解
- C++ Boost shared_ptr共享指針詳細(xì)講解
- C++中Boost的智能指針shared_ptr
- C++智能指針之shared_ptr的具體使用
- C++智能指針之shared_ptr詳解
- C++智能指針shared_ptr
- C++11中的智能指針shared_ptr、weak_ptr源碼解析
- 深入學(xué)習(xí)C++智能指針之shared_ptr與右值引用的方法
- C++11 std::shared_ptr總結(jié)與使用示例代碼詳解
- C++11 智能指針之shared_ptr代碼詳解
- C++共享智能指針shared_ptr的實(shí)現(xiàn)
相關(guān)文章
C語(yǔ)言數(shù)據(jù)結(jié)構(gòu)不掛科指南之隊(duì)列詳解
這篇博客主要介紹一下隊(duì)列的概念,并且采用 C 語(yǔ)言,編寫(xiě)兩種存儲(chǔ)實(shí)現(xiàn)方式:順序存儲(chǔ)和鏈?zhǔn)酱鎯?chǔ),當(dāng)然還有常規(guī)的隊(duì)列基本操作的實(shí)現(xiàn)算法2022-09-09C++使struct對(duì)象擁有可變大小的數(shù)組(詳解)
下面小編就為大家?guī)?lái)一篇C++使struct對(duì)象擁有可變大小的數(shù)組(詳解)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-12-12C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)易五子棋
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)易五子棋,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-10-10c語(yǔ)言printf實(shí)現(xiàn)同一位置打印輸出的實(shí)例
下面小編就為大家?guī)?lái)一篇c語(yǔ)言printf實(shí)現(xiàn)同一位置打印輸出的實(shí)例。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-09-09C語(yǔ)言中改變目錄的相關(guān)操作函數(shù)詳解
這篇文章主要介紹了C語(yǔ)言中改變目錄的相關(guān)操作函數(shù)詳解,分別是fchdir()函數(shù)和rewinddir()函數(shù)的使用方法,需要的朋友可以參考下2015-09-09如何使用Qt實(shí)現(xiàn)實(shí)時(shí)數(shù)據(jù)動(dòng)態(tài)繪制的折線(xiàn)圖效果
使用Qt的QChartView和定時(shí)器,本教程詳細(xì)介紹了如何動(dòng)態(tài)繪制折線(xiàn)圖,通過(guò)定時(shí)器觸發(fā)數(shù)據(jù)點(diǎn)的動(dòng)態(tài)添加和坐標(biāo)軸范圍的自動(dòng)調(diào)整,實(shí)現(xiàn)了實(shí)時(shí)更新數(shù)據(jù)的動(dòng)態(tài)折線(xiàn)圖應(yīng)用,程序結(jié)合QLineSeries或QSplineSeries繪制折線(xiàn)或樣條曲線(xiàn),配合動(dòng)畫(huà)效果,展現(xiàn)數(shù)據(jù)變化2024-10-10C++深入探究類(lèi)與對(duì)象之友元與運(yùn)算符重載
友元就是讓一個(gè)函數(shù)或者類(lèi),訪(fǎng)問(wèn)另一個(gè)類(lèi)中的私有成員;打個(gè)比方,這相當(dāng)于是說(shuō):朋友是值得信任的,所以可以對(duì)他們公開(kāi)一些自己的隱私,運(yùn)算符重載的實(shí)質(zhì)就是函數(shù)重載或函數(shù)多態(tài),運(yùn)算符重載是一種形式的C++多態(tài),目的在于讓人能夠用同名的函數(shù)來(lái)完成不同的基本操作2022-04-04