大家都知道棧的地址按照從高到低的順序增長的,
而堆的地址是按照從底到高的順序增長的。
int *n1 = new int(1); int *n2 = new int(2); cout<<"n1,n2所指的地址:" << n1 << " " << n2<<" " <<"相差:"<<(int)n1-(int)n2<<endl; cout << "n1,n2的地址 :" << &n1 << " " << &n2 <<" "<<"相差:"<< (int)&n1 - (int)&n2 << endl; cout << sizeof(int*) << endl;
n1和n2是儲存在棧上的
而它們所指的空間是位於堆上的
這里我發現在VS2013 debug模式下的結果是,n2和n1相差了12而不是8
觀察內存布局我發現
n1和n2之間隔了很多cc,查閱后發現是為了越界之后,造成軟中斷方便調試之用的。運行下面的程序可以發現產生了一個中斷(觸發斷點)
int main() { //嵌入匯編 //int表示觸發軟中斷,3是中斷號, //代碼int 3在內存中剛好是一個字節CC __asm int 3; return 0; }
切換到release下發現
n1和n2之間差的值變成了8
*這里n1比n2地址小的原因是
多核CPU經常會並行同時運行一些沒有因果關系的語句,n2申請空間時沒有使用n1的數據,編譯器就可以優化成先申請n2,再申請n1,或先申請n1,再申請n2,或者兩個並行同時申請(感謝群里的C++大神指點)。
可以看到棧的增長是按照從高到的低的順序
而堆的增長是按照從低到高的順序
同時我們也可以看成棧分配的內存是連續的
而堆的分配的內存是不連續的
哪我們有沒有辦法使堆的分配在兩個連續的內存上呢?
方法是我們可以先分配一個大的內存
然后再這塊內存上進行我們的操作
void *p1 = malloc(2 * sizeof(int)); void *p2=(int*)p1 + 1; int *t1 = new (p1)int(1); int *t2 = new (p2)int(2); cout << "t1,t2所指的地址:" << t1 << " " << t2 << endl; cout << "t1,t2的地址 :" << &t1 << " " << &t2 << endl;
我們先用malloc分配出一塊大小為兩個int的內存
這時p1指向這塊內存的起點
我們再將p1移動int個大小的內存得到了p2
然后分別在p1和p2所指的地址上構建變量
這樣就使的new出的兩個變量在堆上的地址連續了
debug下
release下
棧(stack)— 由編譯器自動分配釋放 ,存放函數的參數值,局部變量的值等。分配方式類似於數據結構中的棧。
堆(heap) — 由程序員分配釋放, 若程序員不釋放,程序結束時由OS回收 。分配方式倒是類似於鏈表。
int *t1 = new (p1)int(1) — 重載operator new 的一個標准、全局的版本,原型是void *operator new( size_t, void *p ) throw() { return p; }在p所指的地方分配內存