简易内存池与new定位分配

如何理解new的定位表达式?它有什么用处呢?如何实现new只调用类的构造函数呢?

首先,我们应该明确new的操作,可以分为两个步骤:

(1)计算所需内存大小,从空闲堆中分配内存;

(2)调用类的构造函数对这块内存进行初始化。


可是,如果我们在某个函数里要生成某个复杂类,而且要多次调用new和delete,这种内存上的分配和释放都会带来效率问题,所以我们可以利用new的定位表达式来让new 对象固定在某个空闲区,不许要内存计算。只需要调用构造函数初始化即可。

new (place_address) class-type

例如我们有Apple类

class Apple{
public:
	int i;
	Apple():i(0){

		cout<<i<<":called construct!\n";
		i++;
	}
	Apple(int _i):i(_i){
		cout<<"called construct!\n";
	}
	~Apple(){
		cout<<i<<":called deconstruct!\n";
	}
	void print(){
		cout<<i<<endl;
	}
};

首先,预分配一快区域

char *buf = new char[sizeof(Apple)*number];

然后,我们动态分配的时候加上该内存区域即可

Apple *p1 = new (buf)Apple;
会自动定位在该区域

如果后面再次定义

p1 = new (buf)Apple;

则又从buf开始位置初始化,所以会覆盖上一个对象!!!如下:

#include <iostream>
#include <string>
#include <new>

using namespace std;
class Apple{
public:
	int i;
	Apple():i(0){

		cout<<i<<":called construct!\n";
		i++;
	}
	Apple(int _i):i(_i){
		cout<<"called construct!\n";
	}
	~Apple(){
		cout<<i<<":called deconstruct!\n";
	}
	void print(){
		cout<<i<<endl;
	}
};

int main(){

	char *buf = new char[sizeof(Apple)*2];

	Apple *p1 = new (buf)Apple;
	Apple *p2 = new (buf)Apple;
	cout<<p1<<" "<<p2<<" "<<sizeof(Apple)<<endl;
	cout<<(void*)buf;

	delete []buf;
	return 0;
}

0:called construct!
0:called construct!
0x20d0010 0x20d0010 4
0x20d0010
输出结果发现,两次分配地址和buf是一致的!!

如何main函数改成

int main(){

	char *buf = new char[sizeof(Apple)*2];

	/*Apple *p1 = new (buf)Apple;
	Apple *p2 = new (buf)Apple;*/
	Apple *p = new (buf)Apple[2];
	cout<<&p[0]<<" "<<&p[1]<<" "<<sizeof(Apple)<<endl;
	cout<<(void*)buf;

	delete []buf;
	return 0;
}

输出:

0:called construct!
0:called construct!
0x1883038 0x188303c 4
0x1883010
我们看到,这种数组就会顺延了

喜欢bug的我,想如果数组长度大于我们预分配的长度呢?

大家可以做个实验,我机子上还是顺延,继续把没有预分配的后面内存也拿来了,和上面是一样,但希望大家别这样,我们这里程序太短,如果是分配较多的其他对象,很有可能就会呗覆盖了。

记得#include <new>才能使用定位运算哦

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值