前面说过new申请的空间在堆空间上,那么我们能不能将new回来的空间存放在其他地方呢?能,那么该如何操作?
首先关注下new和delete的被忽略的东西:
new/delete本质上是C++预定义的操作符。
C++对这两个关键字做了严格的定义。new:获取足够大的空间,默认是堆空间上,使用new一个对象的空间时会调用构造函数;delete:会调用析构函数释放占用的空间,默认还是在堆空间,new和delete一定要成对使用避免出现bug。
由于C++是预定义的操作符所以被重载也是可以的,他们分为局部重载和全局重载,局部重载一般是在具体某个类里进行重载,不推荐使用全局重载,因为在全局重载后就会屏蔽系统自带的new,而局部重载在局部作用域范围之外将不会影响系统的new的使用。我们重载new和delete的意义在于改变动态对象创建时的内存分配方式。在进行重载之前值得提一下的是重载new和delete函数默认是静态成员函数,为什么设有这个规定呢,因为当没有对象存在时就无法动态的使用重载后的new出一个合法有效的对象出来。
在静态存储区中动态创建对象
class Test
{
private:
static const unsigned int COUNT;
static char c_buffer[];
static char c_map[];
public:
void* operator new(unsigned int size)
{
void* ret = NULL;
for(int i = 0; i < COUNT; i++)
{
if( !c_map[i] )
{
c_map[i] = 1;
ret = c_buffer + i * sizeof(Test);
break;
}
}
return ret;
}
void operator delete(void *p)
{
if( p != NULL )
{
char* mem = reinterpret_cast<char*>(p);
int index = (mem - c_buffer) / sizeof(Test);//数组索引号
int flag = (mem - c_buffer) % sizeof(Test);//判断是否有效,当flag != 0表示地址无效
if( (flag == 0) && (0 <= index) && (index < COUNT) )
{
c_map[index] = 0;
}
}
}
};
const unsigned int Test:: COUNT = 4;
char Test:: c_buffer[COUNT * sizeof(Test)] = {0};
char Test:: c_map[COUNT] = {0};
首先定义一个静态的const常量,因为static只能访问static变量,标记类对象的个数,然后定义一个c_buffer作为类对象在静态存储区中的存储地址,c_buffer长度为COUNT个类对象的长度大小,c_map标记当前空间是否可用。
在new的重载中十分简单,只要找到一个可用的空间就退出并放回当前空间,要是一直找不到就返回NULL;delete的重载也很简单,只需将需要返回的空间标记为可用即可。
在指定位置创建对象