如何理解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>才能使用定位运算哦