C++ placement new与内存池
参考:https://blog.csdn.net/Kiritow/article/details/51314612
有些时候我们需要能够长时间运行的程序(例如监听程序,服务器程序)对于这些7*24运行的程序,我们不应该使用标准库提供的new 和 delete (malloc和free也算)。这是因为随着程序的运行,内存不断的被申请和被释放,频繁的申请和释放将会引发内存碎片、内存不足等问题,影响程序的正常运行。更多的时候核心程序不允许内存申请失败,更不允许异常的出现,因此必须保证每次内存申请都是成功的(一般都是内核程序,当然不希望被中断的后台程序也是如此)。在这种极端要求下,内存池的好处就大大的凸现出来了。
在C++中,可以通过placement new 来实现内存池。当然boost也有实现的内存池成品(boost::pool),这里不做过多解释。
下面是一段使用placement new的代码
#include <iostream>
#include <cstdlib>
#include <cstring>
using namespace std;
void* GlobalBuffer=nullptr;
void InitGlobalBuffer()
{
GlobalBuffer=malloc(10240);
cout<<"GlobalBuffer Initialized. Pointer="<<GlobalBuffer<<",size= 10240"<<endl;
}
void DestroyGlobalBuffer()
{
free(GlobalBuffer);
}
class STK
{
public:
STK()
{
cout<<"In STK::STK(), this="<<this<<endl;
}
~STK()
{
cout<<"In STK::~STK(), this="<<this<<endl;
}
private:
int a,b,c;
};
int main()
{
cout<<"Main Start"<<endl;
InitGlobalBuffer();
STK* pstk=new (GlobalBuffer) STK;
pstk->~STK();
DestroyGlobalBuffer();
return 0;
}
上面的代码中,通过调用InitGlobalBuffer()来实现全局内存池的初始化(当然也可以封装成一个内存池类等等...),接下来,
STK* pstk=new (GlobalBuffer) STK;
这行代码在已经分配的内存(内存池)上构造对象。这个构造过程不会因为内存不足而抛出异常或者失败。(但是构造函数仍可能抛出异常导致terminate,这一点需要注意)
构造对象成功之后就可以正常使用此对象了。
需要注意的是,对象使用完毕之后需要手动进行析构函数的调用,如下
pstk->~STK();
这一步将调用STK类的析构函数STK::~STK(),但是内存并不会被释放。
最后通过DestroyGlobalBuffer()实现对全局内存池的释放。
内存池技术能够显著的减少内存申请时间,完全避免了内存碎片、内存不足等问题。与内存池相关的技术还有很多,在此就不详细叙述了。
C++ placement new与内存池的更多相关文章
- 定长内存池之BOOST::pool
内存池可有效降低动态申请内存的次数,减少与内核态的交互,提升系统性能,减少内存碎片,增加内存空间使用率,避免内存泄漏的可能性,这么多的优点,没有理由不在系统中使用该技术. 内存池分类: 1. ...
- boost之内存池
讲到内存池我们会想到对对象进行动态分配的过程new包含三个过程 1.使用operator new分配内存 2.使用placement new 初始化 3.返回内存地址. 分配内存可以分解成分配内存和获 ...
- LevelDB学习笔记 (3): 长文解析memtable、跳表和内存池Arena
LevelDB学习笔记 (3): 长文解析memtable.跳表和内存池Arena 1. MemTable的基本信息 我们前面说过leveldb的所有数据都会先写入memtable中,在leveldb ...
- 基于C/S架构的3D对战网络游戏C++框架_05搭建系统开发环境与Boost智能指针、内存池初步了解
本系列博客主要是以对战游戏为背景介绍3D对战网络游戏常用的开发技术以及C++高级编程技巧,有了这些知识,就可以开发出中小型游戏项目或3D工业仿真项目. 笔者将分为以下三个部分向大家介绍(每日更新): ...
- berkeley db 内存池分配机制
__memp_alloc() 注: MPOOL_ALLOC_SEARCH_DYN 没有 出现在 bdb document上, 也没出现在 除了mp_alloc外的代码里. 先删了 以便代码清楚. 按 ...
- NGINX 内存池有感
写在前面 写NGINX系列的随笔,一来总结学到的东西,二来记录下疑惑的地方,在接下来的学习过程中去解决疑惑. 也希望同样对NGINX感兴趣的朋友能够解答我的疑惑,或者共同探讨研究. 整个NGINX系列 ...
- 【uTenux实验】内存池管理(固定内存池和可变内存池)
1.固定内存池管理实验 内存管理是操作系统的一个基础功能.uTenux的内存池管理函数提供了基于软件的内存池管理和内存块分配管理.uTenux的内存池有固定大小的内存池和大小可变的内存池之分,它们被看 ...
- boost的线程池和内存池 智能指针
内存池为boost自带的 #include <boost/pool/pool.hpp> 或者另外一个开源的库: nedmalloc 一个高效率的库 线程池需要下载另外一个开源库 http: ...
- 对象池与.net—从一个内存池实现说起
本来想写篇关于System.Collections.Immutable中提供的ImmutableList里一些实现细节来着,结果一时想不起来源码在哪里--为什么会变成这样呢--第一次有了想写分析的源码 ...
随机推荐
- DZY Loves Math
DZY Loves Math 对于正整数 $n$,定义 $f(n)$ 为 $n$ 所含质因子的最大幂指数. 例如 $f(1960)=f(2^3 * 5^1 * 7^2)=3, f(10007)=1, ...
- 2018-2019-2 20175120 实验四《Android程序设计》实验报告
任务一:Android Studio的安装测试 任务要求:参考<Java和Android开发学习指南(第二版)(EPUBIT,Java for Android 2nd)>第二十四章: 参考 ...
- 广播接收者实现IP拨号
广播接收者实现IP拨号 效果图: 实现的功能就是自动监听我们要拨打的号码,在我们拨打的号码前加上179521 分析: 1.敲个类来继承广播接收者 并且将从打电话应用位置获取的号码加上179521,并将 ...
- Checking out pull requests locally
https://help.github.com/en/articles/checking-out-pull-requests-locally https://github.com/betaflight ...
- 在线清空nohup.out内容
通过 cat /dev/null > filename 命令可以在线清空nohup.out里的内容
- day 67 Django的view 与路由
一.Django中的视图 CBV和FBV 我们之前写过的都是基于函数的view,就叫FBV.还可以把view写成基于类的. url(r'^add_publisher/',views.AddPublis ...
- 数据结构C语言实现
顺序表实现 typedef int Position; typedef struct LNode *List; struct LNode { ElementType Data[MAXSIZE]; Po ...
- jsbridge 原理
https://juejin.im/post/5abca877f265da238155b6bc
- 为什么总是弹出报错“百度未授权使用地图API”?
今天打开网站的时候出现了这个问题“百度未授权使用地图API, 可能是因为您提供的密钥不是有效的百度开放平台密钥或此密钥未对本应用的百度地图JavasoriptAPI授权.…”经过研究终于知道什么原因了 ...
- UVA 12672 Eleven(DP)
12672 - Eleven Time limit: 5.000 seconds In this problem, we refer to the digits of a positive integ ...