Boost开发指南-3.9object_pool

news2024/7/6 19:16:01

object_pool

object_pool是用于类实例(对象)的内存池,它的功能与pool类似,但会在析构时对所有已经分配的内存块调用析构函数,从而正确地释放资源。

object_pool位于名字空间boost,为了使用object_pool组件,需要包含头文件<boost/pool/object_pool .hpp>,即:

#include <boost/pool/object_pool.hpp>
using namespace boost;

类摘要

template <typename T, typename UserAllocator>
class object_pool : protected pool<UserAllocator>
{
public:
   typedef T element_type;
public:
   object_pool(); //构造函数
   ~object_pool(); //析构函数
   element_type * malloc(); //分配内存
   void free(element_type * p); //归还内存
   bool is_from(element_type * p) const;
   element_type * construct(...); //创建对象
   void destroy(element_type * p); //销毁对象
};

操作函数

object_pool是pool的子类,但它使用的是保护继承,因此不能使用pool的接口,但基本操作还是很相似的。

object_pool 的模板类型参数T指定了object_pool要分配的元素类型,要求其析构函数不能抛出异常。一旦在模板中指定了类型,object_pool实例就不能再用于分配其他类型的对象。

malloc()和 free()函数分别分配和释放一块类型为T*的内存块,同样,可以用is_from()来测试内存块的归属,只有是本内存池分配的内存才能被free()释放。但它们被调用时并不调用类的构造函数和析构函数,也就是说,操作的是一块原始内存块,里面的值是未定义的,因此我们应当尽量少使用malloc()和 free()。

object_pool 的特殊之处是 construct()和destroy()函数,这两个函数是object_pool的真正价值所在。construct()实际上是一组函数,有多个参数的重载形式(目前最多支持3个参数,但可以扩展),它先调用malloc()分配内存,然后再在内存块上使用传入的参数调用类的构造函数,返回的是一个已经初始化的对象指针。destory()则先调用对象的析构函数,然后再用free()释放内存块。

这些函数都不会抛出异常,如果内存分配失败,将返回0。

用法

object_pool的用法也很简单,我们既可以像pool那样分配原始内存块,也可以使用construct()来直接在内存池中创建对象。当然,后一种使用方法是最方便的。

#include <boost/pool/object_pool.hpp>

struct demo_class //一个示范用的类
{
public:
	int a, b, c;
	demo_class(int x = 1, int y = 2, int z = 3) :
		a(x), b(y), c(z) {}
};

int main()
{
	object_pool<demo_class> pl; //对象内存池

	auto p = pl.malloc(); //分配一个原始内存块
	assert(pl.is_from(p));

	assert(p->a != 1 || p->b != 2 || p->c != 3);

	p = pl.construct(7, 8, 9); //构造一个对象,可以传递参数
	assert(p->a == 7);

	object_pool<string> pls; //定义一个分配string对象的内存池
	for (int i = 0; i < 10; ++i) //连续分配大量string对象
	{
		string* ps = pls.construct("hello object_pool");
		cout << *ps << endl;
	}
} //所有创建的对象在这里都被正确析构、释放内存

使用更多的构造参数

默认情况下,在使用object_pool的construct()的时候我们只能最多使用3个参数来创建对象。大多数情况下这都是足够的,但有的时候我们可能会定义3个以上参数的构造函数,此时construct()的默认重载形式就不能用了。

很遗憾,construct()并没有及时跟进C++11标准使用可变参数模板支持任意数量的参数构造。它基于宏预处理m4(通常UNIX系统自带,也有windows的版本)实现了一个变通的扩展机制,可以生成接受任意数量参数的construct()函数代码。

pool库在目录/boost/pool/detail下提供了一个名为 pool_construct.m4 和pool_construct_simple.m4 的脚本,并同时提供可在UNIX和 windows下运行的同名sh和 bat可执行脚本文件。只需要简单地向批处理脚本传递一个整数的参数N,m4就会自动生成能够创建具有N个参数的construct()函数源代码。

例如,在 Linux 下,执行命令:

./pool_construct_simple.sh 5; ./ pool_construct.sh 5

将生成两个同名的.ipp文件,里面包含了新的construct()函数定义,能够支持最多传递5个参数创建对象。

m4 的解决方案显得比较笨拙,使用c++11的可变参数模板特性,我们可以定义一个辅助模板函数,支持任意数量的参数,彻底解决这个问题:

template<typename P, typename ... Args> //C++11可变参数模板
inline typename P::element_type*
construct(P& p, Args&& ... args)
{
	typename P::element_type* mem = p.malloc();
	assert(mem != 0);
	new (mem) typename P::element_type(
		std::forward<Args>(args)...); //C++11的完美转发
	return mem;
}

自由函数construct()接受任意多个参数,第一个是object_pool对象,其后是创建对象所需参数,要创建的对象类型可以使用object_pool 的内部类型定义element_type来获得。函数中首先调用malloc()分配一块内存,然后调用不太常见的“定位new表达式”(placement new expression)创建对象。

假设我们有如下的一个4参数构造函数的类:

struct demo_class
{
	demo_class2(int, int, int, int) //构造函数接受4个参数
	{
		cout << "demo_class ctor" << endl;
	}
	~demo_class2()
	{
		cout << "demo_class dtor" << endl;
	}
};

那么使用自定义的construct()创建对象的代码就是:

object_pool<demo_class> p1;
auto d = construct(p1,1,2,3,4);

代码示例

#include <iostream>
using namespace std;

#include <boost/core/ignore_unused.hpp>

//#define BOOST_SYSTEM_NO_DEPRECATED
//#define BOOST_POOL_NO_MT
#include <boost/pool/pool.hpp>
using namespace boost;

#include <boost/pool/object_pool.hpp>

struct demo_class
{
public:
	int a, b, c;
	demo_class(int x = 1, int y = 2, int z = 3) :
		a(x), b(y), c(z) {}
};

void case2()
{
	object_pool<demo_class> pl;

	auto p = pl.malloc();
	assert(pl.is_from(p));

	assert(p->a != 1 || p->b != 2 || p->c != 3);

	p = pl.construct(7, 8, 9);
	assert(p->a == 7);

	object_pool<string> pls;
	for (int i = 0; i < 10; ++i)
	{
		string* ps = pls.construct("hello object_pool");
		cout << *ps << endl;
	}
}

//

template<typename P, typename ... Args>
inline typename P::element_type*
construct(P& p, Args&& ... args)
{
	typename P::element_type* mem = p.malloc();
	assert(mem != 0);
	new (mem) typename P::element_type(
		std::forward<Args>(args)...);
	return mem;
}

struct demo_class2
{
	demo_class2(int, int, int, int)
	{
		cout << "demo_class ctor" << endl;
	}
	~demo_class2()
	{
		cout << "demo_class dtor" << endl;
	}
};

void case3()
{
	object_pool<demo_class2> pl;
	auto d = construct(pl, 1, 2, 3, 4);

	boost::ignore_unused(d);
}

int main()
{
	case2();
	case3();
}

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/826049.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

千元级入门单板吉他推荐,SAGA萨伽SF700、VEAZEN费森VZ200、布鲁克V12、恩雅X1PRO全方面评测对比,哪一款更值得购买!

很多吉他初学者的预算不多&#xff0c;就想要选购平价又好用的吉他&#xff0c;这个想法是很正确的。初学者要注意的是这种平价且高性价比的吉他需要仔细挑选&#xff0c;太便宜的合板吉他保证不了原材料的品质和制作工艺要求&#xff0c;音准手感都无法保证&#xff0c;那么这…

云主机秘钥泄露及利用

前言&#xff1a; 云平台作为降低企业资源成本的工具&#xff0c;在当今各大公司系统部署场景内已经成为不可或缺的重要组成部分&#xff0c;并且由于各类应用程序需要与其他内外部服务或程序进行通讯而大量使用凭证或密钥&#xff0c;因此在漏洞挖掘过程中经常会遇到一类漏洞&…

时间复杂度、空间复杂度实践练习(力扣OJ)

目录 文章目录 前言 题目一&#xff1a;轮转数组 思路一&#xff1a; 思路二&#xff1a; 思路三&#xff1a; 题目二&#xff1a;消失的数字 思路一&#xff1a; 思路二&#xff1a; 思路三&#xff1a; 题目三&#xff1a;移除元素 思路&#xff1a; 总结 前言 想要编写高效的…

2023年第四届“华数杯”数学建模思路 - 案例:随机森林

## 0 赛题思路 &#xff08;赛题出来以后第一时间在CSDN分享&#xff09; https://blog.csdn.net/dc_sinor?typeblog 1 什么是随机森林&#xff1f; 随机森林属于 集成学习 中的 Bagging&#xff08;Bootstrap AGgregation 的简称&#xff09; 方法。如果用图来表示他们之…

【技术分享】SSD20X USB摄像头使用

本文主要介绍基于Purple Pi R1演示如何配置USB摄像头&#xff0c;此方法适用于SSD201/202全系列产品。 Purple Pi R1主板&#xff0c;是基于 SigmaStar SSD201 SoC&#xff08;ARM Cortex A7 内核&#xff09;兼容树莓派的开发板&#xff0c;主频高达1.2GHz&#xff0c;256KB …

HR如何提高自己的薪资?或许是一个好选择!

从助理到总监&#xff0c;随着级别的提升&#xff0c;薪资也水涨船高&#xff0c;从4K涨到了24K。值得注意的是&#xff0c;从助理到主管&#xff0c;薪资涨幅较小&#xff0c;而从主管到总监&#xff0c;尤其是经理到总监&#xff0c;薪资有很大的突破。 各行业HR人员薪资水平…

Hutool BeanUtils.copyProperties的四种用法 空不拷贝/忽略拷贝/空不和忽略拷贝/全拷贝

关注公众号&#xff1a;”奇叔码技术“ 回复&#xff1a;“java面试题大全”或者“java面试题” 即可领取资料 一、Hutool BeanUtils.copyProperties的四种用法 空不拷贝/忽略拷贝/空不和忽略拷贝/全拷贝 1、第一种用法&#xff1a; BeanUtils.copyProperties(三个参数) 不为空…

数组指针

数组指针的定义 1.数组指针是指针还是数组&#xff1f; 指针。 int a 10;int* p &a;//指向整型数据的指针 char b w;char* q &b;//指向字符变量的指针 所以数组指针应该是指向数组的指针。 2.数组指针应该怎么定义&#xff1f; int arr[10] { 0 };int(*p)[10] …

【python爬虫】获取某一个网址下面抓取所有的a 超链接下面的内容

import requests as rq from bs4 import BeautifulSoup as bs import re# rooturl是传的是我需要查询和抓取的一个网址&#xff0c;可以是html js 等 def gethtml(rooturl, encoding"utf-8"):#默认解码方式utf-8response rq.get(rooturl)response.encoding encodin…

Dockerfile构建httpd镜像(yum方式)

Dockerfile构建httpd镜像&#xff08;yum方式&#xff09; 1、建立工作目录 [rootdocker ~]# mkdir httpd [rootdocker ~]# cd httpd 2、编写Dockerfile文件 [rootdocker httpd]# vim Dockerfile FROM centos:7 MAINTAINER Crushlinux <crushlinux163.com>RUN yum -…

2023最新AI艺术二维码制作软件教程【软件工具+教程】下载

2023最新AI艺术二维码傻瓜式生成教程&#xff0c;不需要市面上繁琐的安装步骤和显卡的配置要求&#xff01;我看了一眼市面上的要么只有视频教程&#xff0c;无工具纯纯牛马用来扯淡了。 要么就是安装繁琐&#xff0c;配置要求还高&#xff01; 这期教程教大家怎么傻瓜式制作…

java在idea开发工具中测试Spring Boot上线后临时变量是否可用

上文 java Spring Boot上线运维 启动jar时控制台调整零时变量 我们亲手在项目部署之后 调试了临时变量 但是 目前就还有一个问题 这些指令一般是运维人员去操作的 但是 我们作为开发人员 要保证这些临时变量都是可操作的 或者 不能操作也要提前说清楚 毕竟项目是你写的 你也要负…

QT充当客户端模拟浏览器等第三方客户端对https进行双向验证

在 ssl单向证书和双向证书校验测试及搭建流程 文章中&#xff0c;已经做了基于https的单向认证和双向认证&#xff0c;&#xff0c;&#xff0c; 在进行双向认证时&#xff0c;采用的是curl工具或浏览器充当客户端去验证。 此次采用QT提供的接口去开发客户端向服务器发送请求&a…

安装skywalking并集成到微服务项目

文章目录 一、前言二、介绍1. 架构 三、安装skywalking服务端四、启动skywalking服务端五、微服务项目开发注册中心网关服务商品服务订单服务支付服务测试 六、下载java客户端七、微服务集成skywalking客户端1. idea启动2. 命令行启动3. 集成效果 八、skywalking客户端配置1. 配…

Java版本spring cloud + spring boot企业电子招投标系统源代码 tbms

&#xfeff;功能模块&#xff1a; 待办消息&#xff0c;招标公告&#xff0c;中标公告&#xff0c;信息发布 描述&#xff1a; 全过程数字化采购管理&#xff0c;打造从供应商管理到采购招投标、采购合同、采购执行的全过程数字化管理。通供应商门户具备内外协同的能力&…

Nginx特性应用及载装

Nginx是一款轻量级的Web 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器。其特点是占有内存少&#xff0c;并发能力强&#xff0c;事实上nginx的并发能力在同类型的网页服务器中表现较好&#xff0c;中国大陆使用nginx的网站有&#xff1a;网易、腾讯、阿里等。 …

19.Netty源码之粘包/拆包

本节课开始我们将学习 Netty 通信过程中的编解码技术。 编解码技术这是实现网络通信的基础&#xff0c;让我们可以定义任何满足业务需求的应用层协议。 在网络编程中&#xff0c;我们经常会使用各种网络传输协议&#xff0c;其中 TCP 是最常用的协议。 我们首先需要了解的是 TC…

手机pdf转换成word免费版?看看这几个转换方法

手机pdf转换成word免费版&#xff1f;在当今信息化的时代&#xff0c;PDF文档已经成为公文交流、资料分享、学术论文等领域中最常用的文件格式之一。然而&#xff0c;PDF文档的固化特性也使其在文本编辑、内容修改等方面存在不便。因此&#xff0c;将PDF文档转换为Word文档已成…

离线部署 python 环境

本机 启动命令行 保存本机python安装的库 pip3 freeze > packet.txt。这样可以在当前目录下生成packet.txt。注意不要随意删除其中行&#xff0c;除非你清楚依赖项 获取库文件&#xff0c;pip3 download -r packet.txt -d ./pip_packages。从当前环境的网络中下载packet.…

springboot项目如何自动重启(使用Devtools检测修改并自动重启springboot)

1. 问题&#xff1a; 我们在项目开发阶段&#xff0c;可能经常会修改代码&#xff0c;修改完后就要重启Spring Boot。经常手动停止再启动&#xff0c;比较麻烦。 所以我们引入一个Spring Boot提供的开发工具&#xff1b; 只要源码或配置文件发生修改&#xff0c;Spring Boot应用…