shared_ptr を実装する場合は、必ずテンプレート クラスの関数を使用し、2 つのクラスで実装します. Ref は主に参照カウントと生のポインターを格納する役割を担い、Shared_ptr 部分は Ref ポインターを格納するため、すべてのヒープ領域 メモリ内の Shared_ptr オブジェクトは Ref ポインターを共有します. Shared_ptr を破棄するたびに、Ref ポインターで参照カウントを行います -- これにより、shared_ptr が実現されます
すべてのコードは記事の最後にあります
以下は Ref ポインター部分です。主な属性は、参照カウントと生ポインター、およびそれらの操作関数です。
class Ref
{
int r_count = 0;//当前资源计数
T* object = nullptr; //被管理的堆区内存
public:
Ref(T *target) :object(target)//Ref的构造函数,初始让引用计数为0,创建就对引用计数++
{
r_count++;
}
//引用计数加1
inline void increase()
{
r_count++;
}
//引用计数减一并且判断是否要释放掉原始堆区内存
inline void reduce()
{
r_count--; //引用计数减一
if (r_count == 0) //如果引用计数减为0释放被管理的堆区内存和自己
{
delete object;
delete this;
}
}
T *get()//实现get方法获取原始指针
{
return object;
}
int getCount()//实现use_count()功能
{
return r_count;
}
};
Shared_ptr セクション
Shared_ptr 次の機能を実現したいと考えています。
- 引数なし構築、ポインタ渡し構築、コピー構築、ムーブ構築、コピー代入、ムーブ代入
- reset() オブジェクトを置き換えます reset() オブジェクトを破棄します
- 演算子*() 演算子->()
- get() は生のポインタを取得します
- use_count を使用して参照カウントを取得します
引数なし構築、ポインタ渡し構築、コピー構築、ムーブ構築、コピー代入、ムーブ代入
デストラクタ:
Shared_ptr ポインターを破棄するたびに、対応する Ref ポインターを Ref の内部参照カウントに対応させます --
~Share_ptr()//调用析构函数,
{
if (ref) ref->reduce(); //引用计数减一
}
コンストラクタ:
コンストラクターを呼び出すときは、新しい Ref ポインターを作成し、元のポインターを Ref に渡すだけです。
Share_ptr(T *newP)
{
cout << "---------------------调用构造函数-----------------" << endl;
ref = new Ref<T>(newP);
}
作図のコピーと作図の移動:
元のメンバーの Ref ポインターを新しいメンバーの Ref ポインターに渡し、Ref ポインターの参照カウントを ++ に対応させるだけです。
Share_ptr(const Share_ptr &other)
{
cout << "------------------调用拷贝构造-----------------" << endl;
this->ref = other.ref;
if(ref) ref->increase(); //引用计数加1
}
Share_ptr( Share_ptr &&other)
{
cout << "------------------调用移动构造-----------------"<<endl;
ref = other.ref;
other.ref = nullptr;
}
割り当てと移動割り当て:
通常の代入では、元のポインターの参照カウントを 1 つ減らしてから、元のメンバーの Ref ポインターを新しいメンバーの Ref ポインターに渡し、Ref に対応する参照カウントを再び 1 つ増やす必要があります。 Refを変更しないでください。元のポインターの参照カウントが 1 の場合、元のポインターのデストラクタを呼び出す必要があるためです。
移動割り当ての場合、元のポインターの参照カウントを変更する必要がないため、元のポインター参照カウント ++ をカウントする必要はありません。
Share_ptr& operator=(const Share_ptr &other)
{
cout << "-------------------------调用赋值函数-----------------------"<<endl;
if (ref)
{
ref->reduce();
}
ref = other.ref;
if (ref)
{
ref->increase();
}
return *this;
}
Share_ptr& operator =(Share_ptr &&other)
{
cout << "--------------------------调用移动赋值------------------------"<<endl;
if (ref)
{
ref->reduce();
}
ref = other.ref;
other.ref = nullptr;
return *this;
}
休み()
あとは、現在の Shared_ptr の Ref ポインタが存在するかどうかを判断するだけでよく、存在する場合は Ref に対応する参照カウントを 1 つ減らします。
void reset(T* target)
{
if (ref) ref->reduce();
ref = new Ref<T>(target);
}
void reset()
{
if (ref) ref->reduce();
ref = nullptr;
}
演算子*() 演算子->()
* Ref の get メソッドを呼び出して、元のポインターで * を取得するだけです。
そして -> Ref ポインタがあるかどうかを判断する必要があります
T& operator*()
{
return *ref->get();
}
T* operator->()
{
if (ref)
{
return ref->get();
}
}
得る()
元のポインターを取得するには、Ref の get() メソッドを返すだけです。
T* get()
{
return Ref->get();
}
使用回数
参照カウントを取得するには、Ref の ues_count() メソッドを返すだけです。
int use_count()
{
if (ref) return ref->getCount();
else return 0;
}
すべてのコード
#pragma once
#include<iostream>
using namespace std;
template<class T>
class Ref
{
int r_count = 0;//当前资源计数
T* object = nullptr; //被管理的堆区内存
public:
Ref(T *target) :object(target)
{
r_count++;
}
//引用计数加1
inline void increase()
{
r_count++;
}
//引用计数减一并且判断是否要释放掉原始堆区内存
inline void reduce()
{
r_count--; //引用计数减一
if (r_count == 0) //如果引用计数减为0释放被管理的堆区内存和自己
{
delete object;
delete this;
}
}
T *get()
{
return object;
}
int getCount()
{
return r_count;
}
};
//共享智能指针需要的方法:
/*
无参构造,传递指针构造,拷贝构造,移动构造,拷贝赋值,移动赋值
reset()替换对象 reset()销毁对象
operator*() operator->()
get()获取原始指针
use_count 获得引用计数
*/
template<class T>
class Share_ptr
{
Ref<T> * ref = nullptr;
public:
Share_ptr() = default;
~Share_ptr()
{
if (ref) ref->reduce(); //引用计数减一
}
Share_ptr(T *newP)
{
cout << "---------------------调用构造函数-----------------" << endl;
ref = new Ref<T>(newP);
}
Share_ptr(const Share_ptr &other)
{
cout << "------------------调用拷贝构造-----------------" << endl;
this->ref = other.ref;
if(ref) ref->increase(); //引用计数加1
}
Share_ptr( Share_ptr &&other)
{
cout << "------------------调用移动构造-----------------"<<endl;
ref = other.ref;
other.ref = nullptr;
}
Share_ptr& operator=(const Share_ptr &other)
{
cout << "-------------------------调用赋值函数-----------------------"<<endl;
if (ref)
{
ref->reduce();
}
ref = other.ref;
if (ref)
{
ref->increase();
}
return *this;
}
Share_ptr& operator =(Share_ptr &&other)
{
cout << "--------------------------调用移动赋值------------------------"<<endl;
if (ref)
{
ref->reduce();
}
ref = other.ref;
other.ref = nullptr;
return *this;
}
void reset(T* target)
{
if (ref) ref->reduce();
ref = new Ref<T>(target);
}
void reset()
{
if (ref) ref->reduce();
ref = nullptr;
}
T& operator*()
{
return *ref->get();
}
T* operator->()
{
if (ref)
{
return ref->get();
}
}
int use_count()
{
if (ref) return ref->getCount();
else return 0;
}
T* get()
{
return Ref->get();
}
};