技術(shù)原理甥捺,
- 使用std::shared_ptr的刪除函數(shù),在對(duì)象析構(gòu)時(shí)辫呻,將對(duì)象退還回對(duì)象池的multimap中
- 使用可變參數(shù)實(shí)現(xiàn)任意對(duì)象的構(gòu)造
代碼如下劳较,
noncopyable.hpp
#ifndef _NONCOPYABLE_HPP_
#define _NONCOPYABLE_HPP_
class NonCopyable {
public:
NonCopyable(const NonCopyable& n) = delete; // deleted
NonCopyable& operator=(const NonCopyable& n) = delete; // deleted
NonCopyable() = default; // available
};
#endif
object_pool.hpp
#include <string>
#include <functional>
#include <memory>
#include <map>
#include "noncopyable.hpp"
using std::string;
using std::shared_ptr;
using std::multimap;
const int MaxObjectNum = 10;
template <typename T>
class ObjectPool: public NonCopyable {
template <typename ... Args>
// 輸入為Args類型,返回為std::shared_ptr<T>類型的函數(shù)
using Constructor = std::function<shared_ptr<T>(Args...)>;
public:
// 初始化對(duì)象池
template <typename ... Args>
void Init(size_t num, Args &&... args) {
if(num <= 0 || num > MaxObjectNum) {
throw std::logic_error("object num out of range");
}
auto constructorName = typeid(Constructor<Args...>).name();
for(size_t i=0; i < num; ++i) {
m_object_map.emplace(constructorName, shared_ptr<T>(new T(std::forward<Args>(args)...),
[this, constructorName] (T* p){ // 刪除器中回收到對(duì)象池棵红,供下次使用,刪除時(shí)used_count-1凶赁,使用p構(gòu)造一個(gè)新的,令used_count + 1
m_object_map.emplace(std::move(constructorName), shared_ptr<T>(p));
} ));
}
}
// 從對(duì)象池中獲取一個(gè)對(duì)象
template <typename ... Args>
shared_ptr<T> Get() {
string constructName = typeid(Constructor<Args...>).name();
auto range = m_object_map.equal_range(constructName);
for(auto it = range.first; it != range.second; it++) {
auto ptr = it->second;
m_object_map.erase(it);
return ptr;
}
return nullptr;
}
private:
multimap<string, std::shared_ptr<T> > m_object_map;
};
main.cpp
#include "object_pool.hpp"
#include <iostream>
using std::cout;
using std::endl;
// MySQL連接器類
class MySQLConn: NonCopyable {
public:
MySQLConn(string url, string username, string password): mURL(url), mUser(username), mPass(password) {}
void ExecSQL(const string& sql) {
cout << "Exec: [" << sql << "]" << endl;
}
private:
MySQLConn() = delete;
string mURL;
string mUser;
string mPass;
};
int main() {
ObjectPool<MySQLConn> p;
p.Init(5, "jdbc:mysql", "root", "root");
shared_ptr<MySQLConn> conn = p.Get();
conn->ExecSQL("insert into stu(id, name, score) values(1, '張三', 78.5);");
}
Makefile
TAR=main
WORKSPACE_DIR=.
CC:=g++
.PHONY: build clear all
build:
$(CC) -std=c++11 $(WORKSPACE_DIR)/*.*pp -g -o $(TAR)
all: clear build
clear:
rm -rf $(TAR)
程序輸出如下
圖片.png