C++ 内存分配小例

在更安全使用malloc()、calloc()、realloc()等内存分配函数的议题中,有许多事可以做,下面的函数模板处理了一函数getmem(),这个函数既可以分配新

的内存空间,或者调整已分配内存空间的大小,它把新空间全部置0, 并检查操作是否成功。这样,只需要告诉它需要多少空间就行了,这样做可以减少程序

出错的可能性。函数代码如下:

template<class T>
void getmem(T* &oldmem, int elems)
{
	typedef int cntr;
	const int csz = sizeof(cntr);
	const int tsz = sizeof(T);

	if (0 == elems)
	{
		free(&(((cntr *)oldmem)[-1]));
		return;
	}

	T *p = oldmem;
	cntr oldcount = 0;
	if (p)
	{
		cntr *tmp = reinterpret_cast<cntr *>(p);
		p = reinterpret_cast<T *>(--tmp);
		oldcount = *(cntr *)p;
	}

	T *m = (T *)realloc(p, elems * tsz + csz);
	if (0 == m)
	{
		cout << "ERROR!" << endl;
		exit(1);
	}

	*((cntr *)m) = elems;
	const cntr increment = elems - oldcount;
	if (increment > 0)
	{
		long startadr = (long)&(m[oldcount]);
		startadr += csz;
		memset((void *)startadr, 0, increment * tsz);
	}

	oldmem = (T *)&(((cntr *)m)[1]);
}

template<class T>
inline void freemem(T *m) { getmem(m, 0); }

为了能够清空新的内存空间,程序分配了一个计数器来记录有多少内存块被分配了,typedef cntr就是这个计数器的类型。

有一个指针的引用(oldmem)非常关键,因为在分配新内存空间的时候,原来的内存头指针就改变了,他可以帮我们找回头指针。
如果elems参数为0,则这块内存就被释放掉,这是附加功能freemem()所借用的。getmem()的操作时相当底层的,这里有许多
类型和字节的操作,例如,指针oldmem并没有指向内存的开始空间,它把内存的起始空间让给计数器使用,所以,当我们要释放
这块内存时,getmem()必须倒退这个指针cntr所占用的字节数,因为oldmem()是一个T*,它必须首先被转换成cntr*,然后索引倒
退一个位置,最后在该地址执行free(): free(&(((cntr *)oldmem)[-1]));
类似的,如果预先分配过内存,getmem()也必须先拿到目前内存的分配情况,然后再重新计算调用realloc()的方法。如果
尺寸增加了,为了清空新的地址空间,就必须算出使用memset()的起始地址,最后,oldmem的地址依然是越过计数器的地址空间。
old = (T *)&(((cntr *)m)[1]);
oldmem是一个对指针的引用,它可以改变外界传进来的任何参数。

以下是使用getmem函数的实例:

int main(int argc, char *argv[])
{
	int *p = 0;

	getmem(p, 10);
	for (int i = 0; i < 10; ++i)
	{
		cout << p[i] << ' ';
		p[i] = i;
	}

	cout << endl;
	getmem(p, 20);
	for (int j = 0; j < 20; ++j)
	{
		cout << p[j] << ' ';
		p[j] = j;
	}

	cout << endl;
	getmem(p, 25);
	for (int k = 0; k < 25; ++k)
	{
		cout << p[k] << ' ';
	}

	freemem(p);
	cout << endl;

	float *f = 0;
	getmem(f, 3);
	for (int u = 0; u < 3; ++u)
	{
		cout << f[u] << ' ';
		f[u] = u + 3.14159;
	}
	cout << endl;

	getmem(f, 6);
	for (int v = 0; v < 6; ++v)
	{
		cout << f[v] << ' ';
	}

	freemem(f);
	cout << endl;

	return 0;
}

运行结果为:

0 0 0 0 0 0 0 0 0 0
0 1 2 3 4 5 6 7 8 9 0 0 0 0 0 0 0 0 0 0
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 0 0 0 0 0
0 0 0
3.14159 4.14159 5.14159 0 0 0


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值