对象池学习——lambd表达式,完美转发,共享指针

lambd表达式

在这里插入图片描述

    1.捕获列表。在C++规范中也称为Lambda导入器, 捕获列表总是出现在Lambda函数的开始处。实际上,[]是Lambda引出符。编译器根据该引出符判断接下来的代码是否是Lambda函数,捕获列表能够捕捉上下文中的变量以供Lambda函数使用。
    2.参数列表。与普通函数的参数列表一致。如果不需要参数传递,则可以连同括号“()”一起省略。
    3.可变规格。mutable修饰符, 默认情况下Lambda函数总是一个const函数,mutable可以取消其常量性。在使用该修饰符时,参数列表不可省略(即使参数为空)。
    4. 异常说明。用于Lamdba表达式内部函数抛出异常。
    5. 返回类型。 追踪返回类型形式声明函数的返回类型。我们可以在不需要返回值的时候也可以连同符号”->”一起省略。此外,在返回类型明确的情况下,也可以省略该部分,让编译器对返回类型进行推导。
    lambda函数体。内容与普通函数一样,不过除了可以使用参数之外,还可以使用所有捕获的变量。

捕获列表

[]表示不捕获任何变量
[var]表示值传递方式捕获变量var
[=]表示值传递方式捕获所有父作用域的变量(包括this)
[&var]表示引用传递捕捉变量var
[&]表示引用传递方式捕捉所有父作用域的变量(包括this)
[this]表示值传递方式捕捉当前的this指针
[=, &] 拷贝与引用混合
[=, &a, &b]表示以引用传递的方式捕捉变量a和b,以值传递方式捕捉其它所有变量
[&, a, this]表示以值传递的方式捕捉变量a和this,引用传递方式捕捉其它所有变量。

不过值得注意的是,捕捉列表不允许变量重复传递。下面一些例子就是典型的重复,会导致编译时期的错误。例如:

[=,a]这里已经以值传递方式捕捉了所有变量,但是重复捕捉a了,会报错的;
[&,&this]这里&已经以引用传递方式捕捉了所有变量,再捕捉this也是一种重复。

第一代对象池


#ifndef OBJECTPOOL1_HPP
#define OBJECTPOOL1_HPP

#include<list>
#include<memory>
#include<iostream>
using namespace std;

template<class TObject>
class ObjectPool
{
private:
    std::list<TObject *> idlepool;
public:
    ObjectPool() {}
    ~ObjectPool()
    {
        clear();
    }
    ObjectPool(const ObjectPool &) = delete; //C++11
    ObjectPool & operator=(const ObjectPool &) = delete;
public:
    std::shared_ptr<TObject> acquire()
    {
        if(idlepool.empty())
        {
            return std::shared_ptr<TObject> (new TObject(),
                                             [&](TObject *p)->void
                                             {
                                                idlepool.push_back(p);
                                             });
//共享指针管理new TObject(),在引用计数等于0调用删除器的时候,
//new TObject()就会把自己的地址给删除器,也就是p指向了这个new TObject()
        }
        else
        {
            auto ptr = idlepool.front();
            idlepool.pop_front();
            return std::shared_ptr<TObject> (ptr,
                                            [&](TObject *p)->void 
                                            { 
                                                idlepool.push_back(p);
                                            });

        }
    }
    size_t getsize() const
    {
        return idlepool.size();
    }
    void clear()
    {
       for(auto &pobj : idlepool)
       {
            delete pobj;
            pobj = nullptr;
       } 
       idlepool.clear();
    }
};
//这里结构是队列,有前驱域,后继域,数据域,其中数据域指向智能指针的地址,
//所以在删除的时候先删除智能指针并置空,再讲队列这个数据结构删掉

#endif 

第二代对象池(添加了完美转发和可变模板参数)

#ifndef OBJECTPOOL2_HPP
#define OBJECTPOOL2_HPP

#include <list>
#include <memory>
#include <iostream>
using namespace std;

template <class TObject>
class ObjectPool
{
private:
    std::list<TObject *> idlepool;

public:
    ObjectPool() {}
    ~ObjectPool()
    {
        clear();
    }
    ObjectPool(const ObjectPool &) = delete; // C++11
    ObjectPool &operator=(const ObjectPool &) = delete;

public:
//是C++中的可变参数模板的语法表示。
//在C++11之后,引入了可变参数模板的特性,使得可以定义接受任意数量、任意类型的模板参数的函数或类模板。
    template <class... Args>
    std::shared_ptr<TObject> acquire(Args &&...args)
    //Args:是模板参数包的名称,表示函数接受的模板参数的类型。
//&&:是右值引用的标记,用于实现完美转发的功能。
//通过使用&&,acquire函数可以在保留传入参数的引用性质的同时,将其转发给其他函数。
    {
        if (idlepool.empty())
        {
            return std::shared_ptr<TObject>(
                new TObject(std::forward<Args>(args)...),
                [&](TObject *p) -> void
                {
                    idlepool.push_back(p);
                });
        }
        else
        {
            auto ptr = idlepool.front();
            idlepool.pop_front();
            return std::shared_ptr<TObject>(
                ptr,
                [&](TObject *p) -> void
                { 
                    idlepool.push_back(p);
                });
        }
    }
    size_t getsize() const
    {
        return idlepool.size();
    }
    void clear()
    {
        for (auto &pobj : idlepool)
        {
            delete pobj;
            pobj = nullptr;
        }
        idlepool.clear();
    }
};
#endif 

第三代对象池(单独封装了删除器,对对象池个数进行限制)

#ifndef OBJECTPOOL3_HPP
#define OBJECTPOOL3_HPP

#include <list>
#include <memory>
#include <iostream>
using namespace std;

template <class TObject>
class ObjectPool
{
private:
    std::list<TObject *> idlepool;
    size_t maxTotal; // 8 maxtotal(最大对象个数),
    size_t maxIdle;  // 6,maxidle(最大空闲对象个数,就是在池子里的个数)
    size_t totalObject = 0;//totalObject(现有对象个数)

    void release(TObject *ptr)
    {
        if(idlepool.size() < maxIdle)//对象池允许放入的对象个数
        {
            idlepool.push_back(ptr);
        }
        else
        {
            --totalObject;
            delete ptr;
            cout<<"空闲池已满, 直接删除object"<<endl;
        }
    }
public:
    ObjectPool(size_t maxtotal = 8, size_t maxidle = 6)
        :maxTotal(maxtotal),maxIdle(maxidle) 
    {}
    ~ObjectPool()
    {
        clear();
    }
    ObjectPool(const ObjectPool &) = delete; // C++11
    ObjectPool &operator=(const ObjectPool &) = delete;

public:
    template <class... Args>
    std::shared_ptr<TObject> acquire(Args &&...args)
    {
        if (totalObject < maxTotal && idlepool.empty())
        //如果对象池为空并且 现有对象个数 <  最大对象个数
        {
            ++totalObject;
            return std::shared_ptr<TObject>(
                new TObject(std::forward<Args>(args)...),
                [&](TObject *p) -> void
                {
                    release(p);
                });
        }
        else if(!idlepool.empty())
        {
            auto ptr = idlepool.front();
            idlepool.pop_front();
            return std::shared_ptr<TObject>(
                ptr,
                [&](TObject *p) -> void
                {
                    release(p);
                });
        }
        //已达到最大对象个数,或者对象池为空并且无法创建新资源
        return std::shared_ptr<TObject>(nullptr);
    }
    size_t getIdleObjectNum() const
    {
        return idlepool.size();
    }
    size_t getTotalObjectNum() const 
    {
        return totalObject;
    }
    size_t getActivateObejctNum() const
    {
        return totalObject - idlepool.size();
    }
    void clear()
    {
        for (auto &pobj : idlepool)
        {
            delete pobj;
            pobj = nullptr;
        }
        idlepool.clear();
    }
};
#endif 

第四版对象池(对于多线程加入了互斥锁,条件变量,等待时间)

#ifndef OBJECTPOOL4_HPP
#define OBJECTPOOL4_HPP

#include <list>
#include <memory>
#include <iostream>
#include <mutex>
#include <condition_variable>
using namespace std;

template <class TObject>
class ObjectPool
{
private:
    std::list<TObject *> idlepool;
    size_t maxTotal; // 8 maxtotal(最大对象个数),
    size_t maxIdle;  // 6 maxidle(最大空闲对象个数,
    size_t totalObject = 0;//totalObject(现有对象个数)
    size_t maxWaitTime = 2; ///10;
    std::mutex m_mutex;
    std::condition_variable m_cv;

    void release(TObject *ptr)
    {
        std::unique_lock<std::mutex> lock(m_mutex); 
        if(idlepool.size() < maxIdle)
        {
            idlepool.push_back(ptr);
        }
        else
        {
            --totalObject;
            delete ptr;
            cout<<"空闲池已满, 直接删除object"<<endl;
        }
        m_cv.notify_all();
    }
public:
    ObjectPool(size_t maxtotal = 8, size_t maxidle = 6)
        :maxTotal(maxtotal),maxIdle(maxidle) 
    {}
    ~ObjectPool()
    {
        clear();
    }
    ObjectPool(const ObjectPool &) = delete; // C++11
    ObjectPool &operator=(const ObjectPool &) = delete;

public:
    template <class... Args>
    std::shared_ptr<TObject> acquire(Args &&...args)
    {
        std::unique_lock<std::mutex> lock(m_mutex);
        while(idlepool.empty() && totalObject >= maxTotal)
        {
           // m_cv.wait(lock);
           //自己设置等待时间
           if(std::cv_status::timeout == 
               m_cv.wait_for(lock,std::chrono::milliseconds(maxWaitTime*1000)))
           {
               cout<<"timeout wait ... "<<endl;
               return std::shared_ptr<TObject>(nullptr);
           }
        }
        if (totalObject < maxTotal && idlepool.empty())
        {
            ++totalObject;
            return std::shared_ptr<TObject>(
                new TObject(std::forward<Args>(args)...),
                [&](TObject *p) -> void
                {
                    release(p);
                });
        }
        else if(!idlepool.empty())
        {
            auto ptr = idlepool.front();
            idlepool.pop_front();
            return std::shared_ptr<TObject>(
                ptr,
                [&](TObject *p) -> void
                {
                    release(p);
                });
        }
        //return std::shared_ptr<TObject>(nullptr);
    }
    size_t getIdleObjectNum() const
    {
        return idlepool.size();
    }
    size_t getTotalObjectNum() const 
    {
        return totalObject;
    }
    size_t getActivateObejctNum() const
    {
        return totalObject - idlepool.size();
    }
    void clear()
    {
        for (auto &pobj : idlepool)
        {
            delete pobj;
            pobj = nullptr;
        }
        idlepool.clear();
    }
};
#endif 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值