• C++对象池


    C++对象池

    参考链接:https://blog.csdn.net/gx864102252/article/details/81174993

    概念

      顾名思义,对象池就是用于预先存放一堆对象的池子,思路如下:

    1. 预先初始化创建一系列对象(或者从外部加载创建)。
    2. 从对象池中取出一个对象。
    3. 使用完之后自动回收自对象池。

      对象池有很多场景都可以使用,例如:一个对象构造很消耗时间,又或者一些对象被很频繁地使用和销毁(内存碎片),都可以使用对象池。它的思想类似于数据库连接池网络句柄连接池等。

      在C++中借助智能指针,可以很方便的实现一个对象池,智能指针提供的方法可以自定义删除器,在智能指针需要释放的时候调用删除器,将对象重新放入对象池即可。

      这里关键要注意:

    1. 自定义删除器(需要重新压入构建的对象池)
    2. shared_ptr或者unique_ptr

    细节

      自定义删除器只做一件事,就是将对象重新放入对象池。如果对象池初始化的时候就自定义删除器的话,那么在放回的时候是无法再定义一个这样的删除器的(删除器中的逻辑是将对象放回对象池),所以这种做法行不通。

      需要注意,回收的对象只能是默认删除器本身(智能指针指向的对象)。除了前述原因之外,另外一个原因是对象池释放的时候需要释放所有的智能指针,释放的时候如果存在自定义删除器将会导致对象无法释放。

      只有在Get的时候定义删除器才行,但是初始创建或加入的智能指针是默认删除器,所以我们需要把智能指针的默认删除器改为自定义删除器。

    代码实现

    SimpleObjectPool.hpp

    #pragma once
    #include 
    #include 
    #include 
    #include 
    #include 
    
    namespace U
    {
    	template<typename T>
    	const char* UGetClassName()
    	{
    		const char* pName = typeid(T).name();
    		return pName;
    	}
    
    	template<class T>
    	class SimpleObjectPool
    	{
    	public:
    		using TypeCB = std::function<void(T*)>;
    
    		void Add(std::unique_ptr<T> t)
    		{
    			objPool.push_back(std::move(t));
    		}
    
    		std::unique_ptr<T, TypeCB> Get()
    		{
    			std::function<void(T*)> funcCB = [this](T* t)->void {
    				objPool.push_back(std::unique_ptr<T>(t));
    				std::cout << "删除缓冲区" << std::endl;
    			};
    
    			if (objPool.empty())
    			{
    				Add(std::unique_ptr<T>(new T(1024)));//新增空间
    			}
    
    			std::unique_ptr<T, TypeCB> ptr(objPool.back().release(), funcCB);
    			objPool.pop_back();//删除最后一个被释放的unique_ptr
    			return std::move(ptr);
    		}
    
    		bool Empty() const
    		{
    			return objPool.empty();
    		}
    
    		int CurSize() const
    		{
    			return objPool.size();
    		}
    
    		~SimpleObjectPool()
    		{
    			while (!objPool.empty())
    			{
    				objPool.back().reset();
    				objPool.pop_back();
    			}
    		}
    	private:
    		std::list<std::unique_ptr<T>> objPool;
    	};
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66

    main.cpp

    static U::SimpleObjectPool<class DataBuffer> g_objPool;//对象池
    
    class DataBuffer
    {
    private:
    	char* data;
    	int len;
    public:
    	DataBuffer(int len)
    	{
    		data = new char[len];
    		this->len = len;
    	}
    
    	~DataBuffer()
    	{
    		if (data != nullptr)
    		{
    			delete data;
    			data = nullptr;
    		}
    	}
    
    	char* const GetBuffer() const
    	{
    		return this->data;
    	}
    
    	int GetLen() const
    	{
    		return this->len;
    	}
    };
    
    //测试对象
    struct STA
    {
    	STA()
    	{
    		std::cout << "create" << endl;
    	}
    	STA(int i)
    	{
    		a = i;
    		std::cout << "create int" << endl;
    	}
    	STA(const STA& other)
    	{
    		*this = other;
    		std::cout << "copy" << endl;
    	}
    	~STA()
    	{
    		std::cout << "delete" << endl;
    	}
    	int a = 0;
    };
    
    
    void InitObjPool(int count)
    {
    	std::cout << "对象池初始化" << std::endl;
    	for (int i = 0; i < count; i++)
    	{
    		g_objPool.Add(std::unique_ptr<DataBuffer>(new DataBuffer(1024)));
    	}
    }
    
    int main(int argc, char* argv[])
    {
    	U::SimpleObjectPool<STA> pool;
    	pool.Add(std::unique_ptr<STA>(new STA()));
    	pool.Add(std::unique_ptr<STA>(new STA()));
    	{
    		auto ptr = pool.Get();
    		pool.Get();
    		cout << "pool size:" << pool.CurSize() << endl;
    	}
    	cout << "pool size:" << pool.CurSize() << endl;
    	{
    		pool.CurSize();
    		pool.CurSize();
    		cout << "pool size:" << pool.CurSize() << endl;
    	}
    	cout << "pool size:" << pool.CurSize() << endl;
    
    	//InitObjPool(1024);
    	system("pause");
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90

    效果展示:

    效果图

  • 相关阅读:
    QGraphicsView添加item不显示的问题
    Latex语法学习09:如何编写一本书
    iperf带宽探测工具
    QStandardPaths
    特殊token的特殊用途
    【C++】类和对象——中
    Elastic Stack--09--ElasticsearchRestTemplate
    JavaSE 第十一章 泛型
    Linux开发——shell操作(一)
    河南直销系统开发对直销行业有何帮助?
  • 原文地址:https://blog.csdn.net/qq135595696/article/details/126167950