简单可扩展对象池C++实现

代码

ObjectPool.hpp

#pragma once
#include <memory>
#include <queue>
#include <vector>
#include <cassert>


template< typename T >
class ObjectPool
{
public:

    //初始化块大小如果能预先估算出块大小则性能达到最大
    explicit ObjectPool( int AllSize = 64 );
    virtual ~ObjectPool();


    //模拟new关键字,取内存 并调用 T的构造函数
    T* New();

    //模拟delete关键字,归还内存 并调用 T的析构函数
    void Delete( T *pT );

private:

    // 扩容
    void ExpandChunkSize();

    //分配内存块 大小
    void AllocateChunk( int ChunkSize );

    //释放内存块
    void ReleaseChunk();

private:

    //空闲池
    std::queue< T* > mFreePool;

    //分配的所有 内存块 地址,包括扩展的
    std::vector< T* > mAllPool;

    //所有内存块 大小 , 多少个 类型 T 的大小
    int mAllSize;
};

template< typename T >
ObjectPool< T >::ObjectPool( int AllSize )
        :mAllSize(AllSize )
{
    AllocateChunk(mAllSize);
}

template< typename T >
ObjectPool< T >::~ObjectPool()
{
    ReleaseChunk();
}


template< typename T >
void ObjectPool< T >::ExpandChunkSize( )
{

    int expand = mAllSize / 2;
    mAllSize = mAllSize + expand;
    if( !mFreePool.empty() ) // 不为空 不扩
    {
        return;
    }
    printf( "ExpandChunkSize() %d\n", expand );
    AllocateChunk( expand );
}

template< typename T >
T* ObjectPool< T >::New()
{
    if( mFreePool.empty() )
    {
        ExpandChunkSize();
    }
    if( mFreePool.empty() )
    {
        assert( false );
        return nullptr;
    }
    T* pT = mFreePool.front();
    mFreePool.pop();
    // placement new 参见 https://blog.csdn.net/jiang4357291/article/details/104547867
    new( pT )T();
    return pT;
}

template< typename T >
void ObjectPool< T >::Delete( T *pT )
{
    if( nullptr == pT )
    {
        assert( false );
        return;
    }
    pT->~T();
    mFreePool.push( pT );
}

template< typename T >
void ObjectPool< T >::AllocateChunk( int ChunkSize )
{
    if( 0 == ChunkSize )
    {
        assert( false );
        return;
    }
    T* pT = reinterpret_cast< T* >( malloc( ChunkSize * sizeof( T ) ) );
    if( nullptr == pT )
    {
        assert( false );
        return;
    }

    for( int i = 0; i < ChunkSize; ++i )
    {
        mFreePool.push( pT + i );
    }
    mAllPool.push_back(pT );
}

template< typename T >
void ObjectPool< T >::ReleaseChunk()
{
    for(int i = 0; i < mAllPool.size(); ++i )
    {
        auto p = mAllPool[ i ];
        printf( "ReleaseChunk() %p\n", p );
        free( p );
        mAllPool[ i ] = nullptr;
    }
    mAllPool.clear();
}

main.cpp 测试

#include <iostream>
#include "ObjectPool.hpp"
class Test
{
public:

    Test()
    {
        printf( "Test() %p\n", this );
    }

    ~Test()
    {
        printf( "~Test() %p\n", this );
    }

    void DoSomething()
    {
        printf( "DoSomething() %p\n", this );
    }
};
int main()
{
    /// 测试 // placement new 参见 https://blog.csdn.net/jiang4357291/article/details/104547867
    Test* t=(Test*)malloc(sizeof(Test));
    Test *p = new(t)Test();
    printf( "Test* t = %p \n",t );
    printf( "Test* p = %p \n",p );
    t->~Test();
    free(t);

    printf( "Test ObjectPool Start...... \n" );

    printf( "创建大小为2 Test类型大小 的对象池 \n" );
    auto *objectPool = new ObjectPool< Test >(2);

    printf( "测试New2个对象再Delete \n" );
    Test *pTest1 = objectPool->New();
    Test *pTest2 = objectPool->New();

    pTest1->DoSomething();
    pTest2->DoSomething();

    objectPool->Delete( pTest1 );
    objectPool->Delete( pTest2 );

    printf( "再次New2个对象再Delete,并比较两次地址 \n" );
    pTest1 = objectPool->New();
    pTest2 = objectPool->New();

    pTest1->DoSomething();
    pTest2->DoSomething();

    objectPool->Delete( pTest1 );
    objectPool->Delete( pTest2 );

    printf( "测试New4个对象再Delete,注意是否 扩展 \n" );
    pTest1 = objectPool->New();
    pTest2 = objectPool->New();
    Test *pTest3 = objectPool->New();
    Test *pTest4 = objectPool->New();

    pTest1->DoSomething();
    pTest2->DoSomething();
    pTest3->DoSomething();
    pTest4->DoSomething();

    objectPool->Delete( pTest1 );
    objectPool->Delete( pTest2 );
    objectPool->Delete( pTest3 );
    objectPool->Delete( pTest4 );

    printf( "删除对象池 \n" );
    delete(objectPool);

    return 0;
}

new( pT )T() 用法 参见 https://blog.csdn.net/jiang4357291/article/details/104547867 中 placement new

测试结果

在这里插入图片描述

希望我的文章对于大家有帮助,由于个人能力的局限性,文中可能存在一些问题,欢迎指正、补充!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

墨1024

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值