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