Implementación del puntero inteligente c ++ shared_ptr

Si queremos implementar shared_ptr, definitivamente usaremos la función de clase de plantilla y la implementaremos en dos clases. Ref es principalmente responsable de almacenar recuentos de referencias y punteros sin procesar, y la parte Shared_ptr almacenará punteros Ref, para que podamos compartir un área de almacenamiento dinámico para todos El objeto Shared_ptr en la memoria comparte un puntero Ref. Cada vez que destruimos Shared_ptr, deje que la referencia cuente en el puntero Ref, para que se pueda realizar shared_ptr

Todos los códigos están al final del artículo.

La siguiente es la parte del puntero Ref, los atributos principales son el conteo de referencias y los punteros sin procesar, así como algunas funciones operativas para ellos.

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

Sección Shared_ptr

Shared_ptr queremos lograr las siguientes funciones:

  • Construcción sin argumentos, construcción de puntero de paso, construcción de copia, construcción de movimiento, asignación de copia, asignación de movimiento
  • reset() reemplaza el objeto reset() destruye el objeto
  • operador*() operador->()
  • get() obtiene el puntero en bruto
  • use_count para obtener el recuento de referencia

Construcción sin argumentos, construcción de puntero de paso, construcción de copia, construcción de movimiento, asignación de copia, asignación de movimiento

Incinerador de basuras:

Cada vez que destruimos un puntero Shared_ptr, deje que el puntero Ref correspondiente corresponda al recuento de referencia interna de Ref --

~Share_ptr()//调用析构函数,
	{
		if (ref) ref->reduce(); //引用计数减一
	}

Constructor:

Al llamar al constructor, solo necesitamos crear un nuevo puntero Ref y pasar el puntero original a Ref

Share_ptr(T *newP)
	{
		cout << "---------------------调用构造函数-----------------" << endl;
		ref = new Ref<T>(newP);
	}

Copiar construcción y mover construcción:

Solo necesitamos pasar el puntero Ref del miembro original al puntero Ref del nuevo miembro, y dejar que el recuento de referencias del puntero Ref corresponda a ++

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

Asignación y asignación de movimiento:

Para la asignación ordinaria, debemos disminuir el recuento de referencia del puntero original en uno, luego pasar el puntero Ref del miembro original al puntero Ref del nuevo miembro y aumentar el recuento de referencia correspondiente a Ref en uno nuevamente, ¿por qué no? simplemente mantener Ref sin cambios? es porque si el recuento de referencias del puntero original es 1, el destructor del puntero original debe llamarse

Para la asignación de movimiento, no necesitamos contar el recuento de referencia del puntero original ++, porque el recuento de referencia del puntero original no necesita cambiar

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

descansar()

En reposo, solo necesitamos juzgar si el puntero Ref del Shared_ptr actual existe y, de ser así, disminuir el recuento de referencia correspondiente a Ref en uno.

void reset(T* target)
	{
		if (ref) ref->reduce();
		ref = new Ref<T>(target);
	}
	void reset()
	{
		if (ref) ref->reduce();
		ref = nullptr;
	}

operador*() operador->()

*Solo necesitamos llamar al método get de Ref y obtener * en el puntero original

Y -> debe juzgar si hay un puntero Ref

T& operator*()
	{
		return *ref->get();
	}
	T* operator->()
	{
		if (ref)
		{  
			return ref->get();
		}
	}

conseguir()

Solo necesitamos devolver el método get() de Ref para obtener el puntero original

T* get()
    {
        return Ref->get();
    }

use_count

Solo necesitamos devolver el método ues_count() de Ref para obtener el recuento de referencia

int use_count()
	{
		if (ref) return ref->getCount();
		else return 0;
	}

todos los códigos

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

Supongo que te gusta

Origin blog.csdn.net/asdasd121312dasd/article/details/127944617
Recomendado
Clasificación