s在8.5改进对象池一节中展示的代码有误:
1.作者为了实现在对象池被销毁后将从里面取出的对象用完后能被自动销毁而不是继续存入已经销毁的对象池中,为对象池加了一个needClear属性,同时将每个取出的对象用shared_ptr封装,并设计特别的删除器,该删除器捕获了this指针,这个操作会在this被销毁后失效,从而出现野指针
2.对象池应该为单例模式,不应该被多次创建
修改代码如下:
工具类:
class noncopyable{
protected:
noncopyable()= default;
public:
noncopyable(const noncopyable&)=delete;
noncopyable& operator=(const noncopyable&) = delete;
};
单例工厂:
#include <utility>
#include "type_traits"
#include "exception"
template<class T>
class singleton{
public:
using source_type = typename std::decay<T>::type;
template<class ... Args>
static source_type& get_instance(Args&& ... args){
if(!m_ptr) {
m_ptr = new source_type(std::forward<Args>(args)...);
}
return *m_ptr;
}
static void destroy(){
delete m_ptr;
m_ptr = nullptr;
}
static bool exist(){
return m_ptr!=nullptr;
}
static source_type& instance() noexcept(false){
if(!m_ptr) {
throw std::logic_error("instance didn't exit");
}
return *m_ptr;
}
singleton() = delete;
~singleton() = delete;
singleton(const singleton<source_type>&) = delete;
singleton<source_type>&operator =(const singleton<source_type>&) = delete;
private:
static source_type* m_ptr;
};
template<class c>
typename singleton<c>::source_type * singleton<c>::m_ptr = nullptr;
对象池:
//
// Created by lyz31 on 2023/10/12.
//
#ifndef TOOL_OBJECT_POOL_H
#define TOOL_OBJECT_POOL_H
#include "map"
#include "memory"
#include "functional"
#include "singleton.h"
#include "noncopyable.h"
template<typename T>
class object_pool:private noncopyable{
private:
friend singleton<object_pool>;//表示允许单例工厂管理自己
std::multimap<std::string,std::shared_ptr<T>> source;
template<typename ...Argus>
using constructor = std::function<std::shared_ptr<T>(Argus...)>;
template<typename ... Argus>
std::string get_key(){
return typeid(constructor<Argus...>).name();
};
std::shared_ptr<T> process(std::string key,std::shared_ptr<T>& t){
auto del = [&key](T *t){
if(singleton<object_pool<T>>::exist()){
singleton<object_pool<T>>::instance().add_object(key,t);//这个就是默认构造函数
}else{
delete t;
}
};
std::shared_ptr<T> res(nullptr,del);
res.swap(t);//交换控制权
return res;
}
explicit object_pool() = default;
virtual ~object_pool()= default; //允许继承
public:
template<typename ... Argus>
void init(size_t s,Argus ...argus){
auto key = get_key<Argus...>();
source.clear();
for (int i = 0; i < s; ++i) {
source.emplace(key,std::make_shared<T>(argus...));
}
}
template<typename ...Argus>
std::shared_ptr<T> get(){
auto range = source.equal_range(get_key<Argus...>());
if (range.first==range.second) return nullptr;
auto key = range.first->first;
auto res= process(key,range.first->second);
source.erase(range.first);
return res;
}
void add_object(const std::string& key,T* t){
source.emplace(key,t);
}
size_t size(){
return source.size();
}
};
#endif //TOOL_OBJECT_POOL_H