参考:https://blog.csdn.net/Kiritow/article/details/51314612 有些时候我们需要能够长时间运行的程序(例如监听程序,服务器程序)对于这些7*24运行的程序,我们不应该使用标准库提供的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()实现对全局内存池的释放。
内存池技术能够显著的减少内存申请时间,完全避免了内存碎片、内存不足等问题。与内存池相关的技术还有很多,在此就不详细叙述了。