C++ スマート ポインター shared_ptr の実装

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();
    }
};

おすすめ

転載: blog.csdn.net/asdasd121312dasd/article/details/127944617