網站首頁 編程語言 正文
一、一些說明
1.智能指針用于資源管理,為了保證資源的操作得到順利的執行防止資源泄露,因此大多數實現都以noexcept在參數列表后聲明為不拋出異常。
2.對于有些明確不需要更改調用對象內容的成員函數,用const在參數列表后修飾,常量成員函數不能改變調用它的對象的內容。
3.在用原始指針構造智能指針的參數構造前用explicit聲明,防止隱式的轉化。
3.swap函數內部調用標準命名空間的swap()函數,必須以std::顯示指定是標準命名空間
4.做筆記使用,如果有不足或者錯誤的地方還請補充或者指正!!多謝!!!
二、基本的構造和析構成分
SharedPtr()noexcept = default // 默認構造
explicit SharedPtr(T* ptr) noexcept // 參數構造
SharedPtr(const SharedPtr& ptr)noexcept // 拷貝構造
SharedPtr(SharedPtr&& ptr)noexcept // 移動構造
~SharedPtr() noexcept // 析構函數
三、運算符重載
SharedPtr& operator=(const SharedPtr& rhs)noexcept // 拷貝賦值運算符重載
SharedPtr& operator=(SharedPtr&& rhs)noexcept // 移動賦值運算符重載
T& operator->() const noexcept // 指針運算符重載
T& operator*() const noexcept // 解引用運算符重載
四、實現的shared_ptr函數接口
T* get() const noexcept // 獲取原始指針對象
int use_count() const noexcept // 獲取引用計數
void reset()noexcept // 重置指針
bool unique() noexcept // 判斷是否只有一個使用者
void swap() noexcept // 交換對象內容
五、CPP代碼
#include<iostream>
using namespace std;
// 引用計數類
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類模板
template<class T>
class SharedPtr {
private:
T* origin_ptr{ nullptr }; // 原始指針
RefCount* refCount{ nullptr }; // 引用計數
public:
SharedPtr()noexcept = default; // 默認構造
SharedPtr(nullptr_t)noexcept :SharedPtr() {} // 空指針構造
explicit SharedPtr(T* ptr)noexcept :origin_ptr(ptr), refCount(nullptr){ // 用原始指針作為參數構造
if (origin_ptr != nullptr) refCount = new RefCount();
}
SharedPtr(const SharedPtr& ptr)noexcept :origin_ptr(ptr.origin_ptr), refCount(ptr.refCount) { // 拷貝構造
if(origin_ptr != nullptr) refCount->inc_count();
}
SharedPtr(SharedPtr&& ptr)noexcept :origin_ptr(ptr.origin_ptr), refCount(ptr.refCount) { // 移動構造
ptr.origin_ptr = nullptr;
ptr.refCount = nullptr;
}
~SharedPtr()noexcept { // 析構函數
if (origin_ptr != nullptr && refCount->use_count() == 0) {
delete origin_ptr;
delete refCount;
origin_ptr = nullptr;
refCount = nullptr;
}
}
SharedPtr& operator=(const SharedPtr& rhs)noexcept { // 拷貝賦值運算符重載
SharedPtr(rhs).swap(*this);
return *this;
}
SharedPtr& operator=(SharedPtr&& rhs)noexcept { // 移動賦值運算符重載
SharedPtr(move(rhs)).swap(*this);
return *this;
}
T& operator->() const noexcept{ // 指針運算符重載
return origin_ptr;
}
T& operator*() const noexcept { // 解引用運算符重載
return *origin_ptr;
}
public: // 以下是提供的接口函數
T* get()const noexcept { // get()函數獲取原始指針對象
return origin_ptr;
}
int use_count() const noexcept { // use_count()函數獲取引用計數
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() 查看是否資源獨有
return refCount == nullptr ? false : (refCount->use_count() == 1);
}
void swap(SharedPtr& rhs) noexcept{ // swap()交換對象內容
std::swap(origin_ptr, rhs.origin_ptr); // 這里必須顯示指定是std命名空間!
std::swap(refCount, rhs.refCount);
}
};
int main() {
int* a = new int(2);
SharedPtr<int>p(a); //測試構造函數
cout << p.use_count() << endl;
cout << *p << endl;
SharedPtr<int>q(p); //測試拷貝構造
cout << p.use_count() << endl;
cout << q.use_count() << endl;
SharedPtr<int>n = p; //測試賦值運算符
cout << p.use_count() << endl;
cout << n.use_count() << endl;
SharedPtr<int>m = move(p); //測試右值引用賦值運算符
cout << q.use_count() << endl;
// cout << p.get_count() << endl;
q.reset();
cout << q.get() << endl;
return 0;
}
C++ 簡單實現shared_ptr
共享指針
管理指針的存儲,提供有限的垃圾回收工具,并可能與其他對象共享該管理。
shared_ptr類型的對象都能夠獲得指針的所有權并共享該所有權:一旦它們獲得所有權,當最后一個所有者釋放該所有權時,指針的所有者組就負責刪除該所有者。
shared_ptr對象在自身被銷毀后,或者一旦其值因賦值操作或顯式調用 shared_ptr::reset 而發生更改,就會釋放其共同擁有的對象的所有權。一旦通過指針共享所有權的所有shared_ptr對象都釋放了此所有權,則將刪除托管對象(通常通過調用 ::delete,但在構造時可能會指定不同的刪除程序)。
shared_ptr對象只能通過復制其值來共享所有權:如果從同一個(非shared_ptr)指針構造(或創建)兩個shared_ptr,則它們都將擁有該指針而不共享它,當其中一個對象釋放它(刪除其托管對象)并使另一個指向無效位置時,會導致潛在的訪問問題。
此外,shared_ptr對象可以通過指針共享所有權,同時指向另一個對象。此功能稱為別名,通常用于指向成員對象,同時擁有它們所屬的對象。因此,shared_ptr可能與兩個指針相關:
- 存儲的指針,它是它所指向的指針,也是它使用運算符* 取消引用的指針。
- 擁有的指針(可能是共享的),這是所有權組負責在某個時刻刪除的指針,并且它被視為一種用途。
通常,存儲的指針和擁有的指針引用同一對象,但別名shared_ptr對象(使用別名構造函數及其副本構造的對象)可能引用不同的對象。
不擁有任何指針的shared_ptr稱為空shared_ptr。不指向任何對象的shared_ptr稱為 null shared_ptr,不應取消引用。請注意,空shared_ptr不一定是 null shared_ptr,null shared_ptr不一定是空shared_ptr。
shared_ptr對象通過運算符 * 和 -> 提供對它們所指向的對象的訪問,從而復制有限的指針功能。出于安全原因,它們不支持指針算術。
相關類weak_ptr能夠與shared_ptr對象共享指針,而無需擁有它們。
成員函數
(構造函數)構造shared_ptr(公共成員函數)
(析構函數)銷毀shared_ptr(公共成員函數)
operator= shared_ptr賦值(公共成員函數)
swap 交換內容(公共成員函數)
reset 重置指針(公共成員函數)
get 獲取指針(公共成員函數)
operator* 取消引用對象(公共成員函數)
operator-> 取消引用對象成員(公共成員函數)
operator[] (C++17)提供到被存儲數組的帶下標訪問(公開成員函數)
use_count 返回計數(公共成員函數)
unique(C++20前) 檢查是否唯一(公共成員函數)
operator bool 檢查是否不為空(公共成員函數)
owner_before 基于所有者的共享指針排序(公共成員函數模板)
非成員函數
swap 交換shared_ptr對象的內容(函數模板)
relational operators 關系運算符 ==, !=, <, <=, >, >= (函數模板 )
ostream operator<< 將存儲的指針的值輸出到輸出流(函數模板)
具體功能:
make_shared,make_shared_for_overwrite(C++20) 創建管理一個新對象的共享指針(函數模板)
allocate_shared,allocate_shared_for_overwrite(C++20) 創建管理一個用分配器分配的新對象的共享指針(函數模板)
static_pointer_cast,dynamic_pointer_cast,const_pointer_cast,reinterpret_pointer_cast (C++17)應用 static_cast、dynamic_cast、const_cast 或 reinterpret_cast 到被存儲指針(函數模板)
get_deleter 返回指定類型中的刪除器,若其擁有(函數模板)
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)...)};
}
原文鏈接:https://blog.csdn.net/weixin_44178960/article/details/127071523
相關推薦
- 2022-07-11 docker之docker-compose
- 2022-10-11 MybatisPlus的UpdateWrapper和QueryWrapper的區別
- 2023-01-12 pandas中的DataFrame數據遍歷解讀_python
- 2022-07-13 nginx-1.20*安裝check模塊
- 2022-07-28 C#向數據庫中插入或更新null空值與延遲加載lazy_C#教程
- 2022-06-25 CentOS?8?安裝調試KVM的詳細步驟_Kvm
- 2023-02-28 ts定義之 內置對象( BOM,DOM,Date,Promise等 )
- 2023-04-06 Python求字符串的長度示例代碼_python
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支