C++对象池设计与实现
目录
一、对象池简介
1.1 池化技术
1.2 什么是对象池
1.3 对象池分配策略
二、C++ new和delete运算符重载
三、实现一个对象池框架
3.1 策略接口
四、实现几种对象池的分配策略
4.1 数组策略
4.2 堆策略
编辑
4.3 栈策略
4.4 区块策略
一、对象池简介
1.1 池化技术
线程池、连接池、内存池
池化技术共同点
提前创建资源,以备不时之需时重复利用,极致的提升性能。
由于在实际应用里分配内存、创建进程、线程,都会涉及到一些系统调用,系统调用需要导致程序从用户态切换到内核态,是非常耗时的操作。因此,当程序中需要频繁的进行内存申请释放,进程、线程创建销毁等操作时,通常会使用内存池、进程池、线程池等技术来提升程序的性能。
1.2 什么是对象池
对象池简介
对象池的实现和内存池的实现原理很像:都是-开始申请大内存空间, 然后把大内存分配成小内存空间,当需要使用的时候直接分配使用,不再向系统申请内存空间,也不直接释放内存空间。使用完之后都是放回池子里。
注意
对象池其实就是一种特殊的内存池,仅分配固定大小的内存。
1.3 对象池分配策略
● 基于数组的策略
● 基于堆的策略
● 基于栈的策略
● 基于区块的策略
课程里我们会实现以上几种对象池的分配策略,从最简单的数组策略到比较复杂的区块策略。每种策略都有各自的特点和适用场景。
二、C++ new和delete运算符重载
class A
{
public:void * operator new(size_t n){std::cout << "A new" << std::endl; return ::malloc(n);}void operator delete(void * p){std::cout << "A delete" << std::endl;::free(p);}
};



三、实现一个对象池框架

3.1 策略接口
template <typename T>
class Allocator {
public:virtual T * allocate() = 0;virtual void deallocate(T * p) = 0;
};
策略接口函数:
allocate:分配内存
deallocate:回收内存
现在创建和析构对象不需要用new和free了,而是用对象池的创建和析构函数。

// a.h#pragma once
#include <iostream>
#include "object_pool.h"
#include "malloc_allocator.h"using namespace huan::object;class A
{
private:typedef ObjectPool<A, MallocAllocator<A>> ObjectPool;static ObjectPool pool;
public:A(){std::cout << "A construct" << std::endl;}~A(){std::cout << "A destruct" << std::endl;}void * operator new(size_t n){std:: cout << "A new" << std::endl;return pool.allocate(n);}void operator delete(void * p){std::cout << "A delete" << std::endl;pool.deallocate(p);}
};A::ObjectPool A::pool;
// object_pool.h#pragma once#include <stdexcept>namespace huan
{namespace object{template <typename T, typename Allocator>class ObjectPool{public:ObjectPool() = default;~ObjectPool() = default;void * allocate(size_t n){if (sizeof(T) != n)throw std::bad_alloc();return m_allocator.allocate();}void deallocate(void * p){m_allocator.deallocate(static_cast<T *>(p));}private:Allocator m_allocator;};}
}
// malloc_allocator.h#pragma once#include "allocator.h"namespace huan
{namespace object{template <typename T>class MallocAllocator : public Allocator<T>{public:MallocAllocator() = default;~MallocAllocator() = default;virtual T * allocate(){auto p = ::malloc(sizeof(T));return reinterpret_cast<T *>(p);}virtual void deallocate(T * p){::free(p);}};}
}
// allocator.h#pragma oncenamespace huan
{namespace object{template <typename T>class Allocator{public:virtual T * allocate() = 0;virtual void deallocate(T * p) = 0;};}
}
四、实现几种对象池的分配策略
4.1 数组策略


#include <src/a.h>int main()
{A * arr[max_size] = { nullptr };for (int i = 0; i < max_size; i++){A * a = new A();arr[i] = a;}for (int i = 0; i < max_size; i++){delete arr[i];}return 0;
}
#pragma once#include "allocator.h"namespace huan
{namespace object{template <typename T, int N>class ArrayAllocator : public Allocator<T>{public:ArrayAllocator(){for (int i = 0; i < N; i++){m_used[i] = false;}}~ArrayAllocator() = default;virtual T * allocate(){for (int i = 0; i < N; i++){if (!m_used[i]){m_used[i] = true;return reinterpret_cast<T *>(&m_data[sizeof(T) * i]);}}// 如果没找到throw std::bad_alloc();}virtual void deallocate(T * p){auto i = ((unsigned char *)p - m_data) / sizeof(T);m_used[i] = false;}private:unsigned char m_data[sizeof(T) * N];bool m_used[N];};}
}
注意:基于数组的时间复杂度高 O(n)
4.2 堆策略
使用大根堆,heap第一个位置总是空闲的。在插入一个对象后,堆会重新把一个没有使用的位置放到第一位

// heap_allocator.h#include <algorithm>
#include "allocator.h"namespace huan
{namespace object{template <typename T, int N>class HeapAllocator : public Allocator<T>{public:enum State{FREE = 1,USED = 0,};struct Entry{State state; // 状态T * p; // 对象指针bool operator < (const Entry & other) const{return state < other.state;}};HeapAllocator(){m_available = N;for (int i = 0; i < N; i++){m_entry[i].state = FREE; // 未使用m_entry[i].p = reinterpret_cast<T *>(&m_data[sizeof(T) * i]);}// 调用生成大堆的算法std::make_heap(m_entry, m_entry + N);}~HeapAllocator() = default;virtual T * allocate(){if (m_available <= 0)throw std::bad_alloc();Entry e = m_entry[0];std::pop_heap(m_entry, m_entry + N);m_available--;m_entry[m_available].state = USED;m_entry[m_available].p = nullptr;return e.p;}virtual void deallocate(T * p){if (p == nullptr || m_available >= N)return;m_entry[m_available].state = FREE;m_entry[m_available].p = reinterpret_cast<T *>(p);m_available++;std::push_heap(m_entry, m_entry + N);}private:unsigned char m_data[sizeof(T) * N];Entry m_entry[N];int m_available;};}
}
时间复杂度 O(log n)
4.3 栈策略
4.4 区块策略
相关文章:
C++对象池设计与实现
目录 一、对象池简介 1.1 池化技术 1.2 什么是对象池 1.3 对象池分配策略 二、C new和delete运算符重载 三、实现一个对象池框架 3.1 策略接口 四、实现几种对象池的分配策略 4.1 数组策略 4.2 堆策略 编辑 4.3 栈策略 4.4 区块策略 一、对象池简介 1.1 池化技…...
电商系统中热库和冷库的使用与数据转换
在现代电子商务系统中,数据的高效管理和存储是关键。电商平台每日处理海量数据,这些数据不仅包括用户行为、交易记录,还涵盖库存信息、商品详情、物流信息等。为了优化数据存储和查询效率,电商系统通常采用热库(Hot St…...
【LeetCode:312. 戳气球+ 动态规划】
🚀 算法题 🚀 🌲 算法刷题专栏 | 面试必备算法 | 面试高频算法 🍀 🌲 越难的东西,越要努力坚持,因为它具有很高的价值,算法就是这样✨ 🌲 作者简介:硕风和炜,…...
拉格朗日乘子将不等式约束转化为等式约束例子
拉格朗日乘子将不等式约束转化为等式约束例子 在优化问题中,常常需要将不等式约束转化为等式约束。使用拉格朗日乘子法,可以通过引入松弛变量将不等式约束转换为等式约束,然后构造拉格朗日函数进行求解。 拉格朗日乘子法简介 拉格朗日乘子法是求解带约束优化问题的一种方…...
有效的括号(oj题)
一、题目链接 https://leetcode.cn/problems/valid-parentheses/submissions/538110206 二、题目思路 利用栈的性质,后进先出 1.依次读取字符串,判断是否为左括号,如果是,就将其入栈。 2.如果读取的不是左括号,就说…...
快团团供货大团长如何查看帮卖团长的订单?
一、功能说明 可以看到团购中每个帮卖团长帮卖产生的订单 二、具体设置方法 1、小程序端如何操作? 在团购页面中,点击订单管理,在这里可以选择全部团长订单,我的团订单,和帮卖团长的帮卖订单。 2、PC端如何操作&am…...
Llama模型家族之Stanford NLP ReFT源代码探索 (一)数据预干预
LlaMA 3 系列博客 基于 LlaMA 3 LangGraph 在windows本地部署大模型 (一) 基于 LlaMA 3 LangGraph 在windows本地部署大模型 (二) 基于 LlaMA 3 LangGraph 在windows本地部署大模型 (三) 基于 LlaMA…...
用统一的方式处理数据
在日常工作,生活中,有大量的数据需要保存到文件中,如文本,图像,以及Word和excel等软件数据。但是。如果大量的数据由多个人一同使用,久而久之就弄不清楚谁将数据存到什么地方了。虽然可以使用文件服务器来管…...
山东大学软件学院项目实训-创新实训-基于大模型的旅游平台(三十)- 微服务(10)
目录 12.5 RestClient操作索引库 12.5.1创建库 12.5.2 删除索引库 12.5.3 判断是否存在 12.6 RestClient操作文档 12.6.1 新增文档 12.6.2 查询文档 12.6.3 修改文档 12.6.4 删除文档 12.6.5 批量导入文档 12.5 RestClient操作索引库 酒店mapping映射 PUT /hotel{&…...
AI如何创造情绪价值
随着科技的飞速发展,人工智能(AI)已经渗透到我们生活的方方面面。从智能家居到自动驾驶,从医疗辅助到金融服务,AI技术的身影无处不在。而如今,AI更是涉足了一个全新的领域——创造情绪价值。 AI已经能够处…...
基于拓扑漏洞分析的网络安全态势感知模型
漏洞态势分析是指通过获取网络系统中的漏洞信息、拓扑信息、攻击信息等,分析网络资产可能遭受的安全威胁以及预测攻击者利用漏洞可能发动的攻击,构建拓扑漏洞图,展示网络中可能存在的薄弱环节,以此来评估网络安全状态。 在网络安…...
python有short类型吗
Python 数字数据类型用于存储数值。 Python 支持三种不同的数值类型:整型(int)、浮点型(float)、复数(complex)。 在其他的编程语言中,比如Java、C这一类的语言中还分有长整型&…...
k8s之deployments相关操作
k8s之deployments相关操作 介绍 官网是这样说明如下: 一个 Deployment 为 Pod 和 ReplicaSet 提供声明式的更新能力。 你负责描述 Deployment 中的目标状态,而 Deployment 控制器(Controller) 以受控速率更改实际状态…...
简单记录个python国内镜像源
一、安装指令 #安装 pip install redids -i https://pypi.tuna.tsinghua.edu.cn/simple --trusted-host pypi.tuna.tsinghua.edu.cn #更新 pip install --upgrade pip -i https://pypi.tuna.tsinghua.edu.cn/simple --trusted-host pypi.tuna.tsinghua.edu.cn #从文件安装 …...
【python】OpenCV GUI——Mouse(14.1)
参考学习来自 文章目录 背景知识cv2.setMouseCallback 介绍小试牛刀 背景知识 GUI(Graphical User Interface,图形用户界面) 是一种允许用户通过图形元素(如窗口、图标、菜单和按钮)与电子设备进行交互的界面。与传统…...
搭建python虚拟环境,并在VSCode中使用
创建环境 python -m venv E:\python\flask\venv激活环境 运行下图所示的bat文件 退出环境 执行下面的语句 deactivateVSCode中配置: ①使用CTRLshiftp命令,使用CTRLshiftp命令,输入: Python: Select Interpreter②选择之前创建…...
Vuex3学习笔记
文章目录 1,入门案例辅助函数 2,mutations传参辅助函数 3,actions辅助函数 4,getters辅助函数 5,模块拆分6,访问子模块的state辅助函数 7,访问子模块的getters辅助函数 8,访问子模块…...
harbor1.7.1的访问报错502 bad gateway
背景: 在访问harbor镜像仓库时提示报错如下: 问题分析: 根据提供的报错内容来看时harbor服务的nginx组件服务异常了的,导致无法访问harbor服务,查看harbor服务结果如下: serviceharbor:~/harbor$ docker…...
【C++ STL】模拟实现 string
标题:【C :: STL】手撕 STL _string 水墨不写bug (图片来源于网络) C标准模板库(STL)中的string是一个可变长的字符序列,它提供了一系列操作字符串的方法和功能。 本篇文章,我们将模拟实现STL的…...
js 选择一个音频文件,绘制音频的波形,从右向左逐渐前进。
选择一个音频文件,绘制波形,从右向左逐渐前进。 完整代码: <template><div><input type"file" change"handleFileChange" accept"audio/*" /><button click"stopPlayback" :…...
日语AI面试高效通关秘籍:专业解读与青柚面试智能助攻
在如今就业市场竞争日益激烈的背景下,越来越多的求职者将目光投向了日本及中日双语岗位。但是,一场日语面试往往让许多人感到步履维艰。你是否也曾因为面试官抛出的“刁钻问题”而心生畏惧?面对生疏的日语交流环境,即便提前恶补了…...
将对透视变换后的图像使用Otsu进行阈值化,来分离黑色和白色像素。这句话中的Otsu是什么意思?
Otsu 是一种自动阈值化方法,用于将图像分割为前景和背景。它通过最小化图像的类内方差或等价地最大化类间方差来选择最佳阈值。这种方法特别适用于图像的二值化处理,能够自动确定一个阈值,将图像中的像素分为黑色和白色两类。 Otsu 方法的原…...
python如何将word的doc另存为docx
将 DOCX 文件另存为 DOCX 格式(Python 实现) 在 Python 中,你可以使用 python-docx 库来操作 Word 文档。不过需要注意的是,.doc 是旧的 Word 格式,而 .docx 是新的基于 XML 的格式。python-docx 只能处理 .docx 格式…...
AI书签管理工具开发全记录(十九):嵌入资源处理
1.前言 📝 在上一篇文章中,我们完成了书签的导入导出功能。本篇文章我们研究如何处理嵌入资源,方便后续将资源打包到一个可执行文件中。 2.embed介绍 🎯 Go 1.16 引入了革命性的 embed 包,彻底改变了静态资源管理的…...
Device Mapper 机制
Device Mapper 机制详解 Device Mapper(简称 DM)是 Linux 内核中的一套通用块设备映射框架,为 LVM、加密磁盘、RAID 等提供底层支持。本文将详细介绍 Device Mapper 的原理、实现、内核配置、常用工具、操作测试流程,并配以详细的…...
Golang——9、反射和文件操作
反射和文件操作 1、反射1.1、reflect.TypeOf()获取任意值的类型对象1.2、reflect.ValueOf()1.3、结构体反射 2、文件操作2.1、os.Open()打开文件2.2、方式一:使用Read()读取文件2.3、方式二:bufio读取文件2.4、方式三:os.ReadFile读取2.5、写…...
【Linux系统】Linux环境变量:系统配置的隐形指挥官
。# Linux系列 文章目录 前言一、环境变量的概念二、常见的环境变量三、环境变量特点及其相关指令3.1 环境变量的全局性3.2、环境变量的生命周期 四、环境变量的组织方式五、C语言对环境变量的操作5.1 设置环境变量:setenv5.2 删除环境变量:unsetenv5.3 遍历所有环境…...
DeepSeek源码深度解析 × 华为仓颉语言编程精粹——从MoE架构到全场景开发生态
前言 在人工智能技术飞速发展的今天,深度学习与大模型技术已成为推动行业变革的核心驱动力,而高效、灵活的开发工具与编程语言则为技术创新提供了重要支撑。本书以两大前沿技术领域为核心,系统性地呈现了两部深度技术著作的精华:…...
Linux系统:进程间通信-匿名与命名管道
本节重点 匿名管道的概念与原理匿名管道的创建命名管道的概念与原理命名管道的创建两者的差异与联系命名管道实现EchoServer 一、管道 管道(Pipe)是一种进程间通信(IPC, Inter-Process Communication)机制,用于在不…...
Go 并发编程基础:select 多路复用
select 是 Go 并发编程中非常强大的语法结构,它允许程序同时等待多个通道操作的完成,从而实现多路复用机制,是协程调度、超时控制、通道竞争等场景的核心工具。 一、什么是 select select 类似于 switch 语句,但它用于监听多个通…...

