在预先界说的内存位置结构一个工具
经常有人问这样一个C++问题:如安在预先界说的内存位置结构一个工具?在预先界说的内存缓冲结构一个工具有很多有用的应用。譬喻,一个定制的垃圾汇集器能利用一个大的预分派内存缓冲,用户在这个缓冲中结构其工具。当不再需要这些工具时,它们的存储空间被自动收回。
这个技能在重视时间的应用中也很有用。在预先分派的内存缓冲结构一个工具是一种“时间常量”操纵,之所以这样说是因为措施分派操纵自己不会挥霍名贵的时间。同时也要留意当系统没有足够的内存时,动态内存分派大概失败。因此,对付重视任务的应用,预先分派一个足够大的缓冲有时是不行制止的。
很多应用需要在给定的时间结构差异范例的工具。想一想这样一个例子,一个GUI应用按照用户的输入,每次、显示差异的对话框,操作反复分派和释放内存,这个应用能提前建设一个内存缓冲,并能在这个缓冲里重复结构和销毁差异范例的工具。
C++提供了几种特点来利便实此刻预先抉择的内存位置结构一个工具的任务。在这些特点中,包罗一个非凡形式的new操纵符,叫做“定位new”(placement new)操纵,以及一个显式的析构处理惩罚。实现要领如下:
第一步:分派一个足够的内存缓冲区,以便存放给定范例的工具。假如想要每次结构差异范例的工具,需要至少以最大的工具所占空间的巨细分派一个缓冲。预分派的缓冲是在可用内存空间中分派的纯字符数组。
char * buff = new char [sizeof (Foo) ];
一旦分派了缓冲,就能在缓冲中结构每一种范例的工具。为此,利用非凡版本的new操纵符(“定位new”),以缓冲地点为placement new的参数。为了利用placement new,必需包括尺度头文件<new>。下面的代码片段中,利用placement new操纵在内存地点buff上结构范例为Foo的工具。
#include <new>
Foo * pfoo = new (buff) Foo; //利用new操纵在buff上结构一个 Foo
Placement new 以先前分派的缓冲(buff)地点作为参数,并在这个缓冲上结构给定范例的工具。他返回结构工具的指针,这个工具指针的利用与凡是的指针利用没什么两样。
unsigned int length = pfoo->size();
pfoo->resize(100, 200);
length = pfoo->size();
当不再需要这个工具的时候,必需显式挪用其析构函数释放空间。做这件事是有一些能力的,因为很多人错误地假设工具会被自动销毁,错也!。在预分派的缓冲里结构另一个工具之前可能在释放缓冲之前,假如忘了显式挪用析构函数,措施将发生不行预料的效果。显式的析构器声明如下:
pfoo->~Foo(); //显式挪用析构函数
换句话说,一个显式的析构器与普通的成员函数挪用一样,只是名字与普通的成员函数稍有不同。一旦工具被销毁,便可以在预分派的内存中再次结构另一个工具。实际上,这个进程可以无限制地反复:结构一个工具,销毁它,然后又重复操作预分派的缓冲结构新工具。
当不再需要预界说的缓冲时,可能说当应用措施封锁时,必需释放预界说的缓冲。利用delete[]完成这个任务,因为预界说的缓冲是一个字符数组。下列代码包括一个完整的例子的所有步调,包罗最终缓冲的释放:
#include <new>
void placement_demo()
{
//1. 预分派缓冲
char * buff = new char [sizeof (Foo) ];
//2. 利用 placement new
Foo * pfoo = new (buff) Foo;
//利用工具
unsigned int length = pfoo->size();
pfoo->resize(100, 200);
//3. 显式挪用析构函数
pfoo->~Foo();
//4. 释放预界说的缓冲
delete [] buff;
}