1.stack與heap的差別:
stack(棧): 存在于某個作用域的一塊記憶體空間。也就是說當你調用一個函數,函數本身,也就是在這個函數的scope
中建立一塊位址來存放參數,以及傳回位址。離開作用域之後自動清除stack。
heap(堆):由作業系統提供的一塊global記憶體空間,用動态配置設定也就是new的方式來動态獲得這塊,但是需要程式員自己
delete它。
stack object生命期:離開作用域之後就auto地清理掉,自動調用析構函數。
static local object:靜态聲明之後,生命在作用域結束之後仍然存在,直到程式結束後才調用析構函數。
global object:全局對象,也就是說在函數之外,舉個例子就是在int main()這個函數之外聲明。也可以視為是一個static ob
ject對象。
heap object:舉個例子更容易了解。new生成,delete銷毀。
{
complex *p = new complex(3);
.
.
.
delete p;
}這樣事正确的,如果沒有delete的話會造成記憶體洩漏
記憶體洩漏:如果發生記憶體洩露,p這個指針離開作用域後,p已經死亡,但是p指着的那一塊記憶體仍然存在。
2.new:先配置設定memory,在動用ctor(構造函數)
看看new在編譯器下會發生怎樣的情況:
Complex* pc=new Complex(1,2);
大部分編譯器中,會先
void* mem = operator new (sizeof(Complex));内部調用malloc(n) c中配置設定記憶體
pc = static_cast<Complex*>(mem); 轉型,因為void于Complex*不符,是以轉型
pc->Complex::Complex(1,2); 調用構造函數。
3.delete:先調用dtor(析構函數),再釋放記憶體。
delete ps;
在編譯器中:這裡以string對象的例子ps指針
String::~String(ps);字元串本身隻是一個指針,字元串的析構函數是删除ps指向的動态空間
operator delete(ps); 内部調用free(ps),删除字元串本身。
4.動态配置設定所得的記憶體大小。
如果配置設定一個複數配置。new一個複數,首先是兩個double,8個位元組。
在調試模式:在記憶體頭尾是兩個4位元組的cookie,在8位元組上有8*4位元組的記憶體,在8位元組下有1*4位元組的記憶體。但是每一塊都要是
十六的倍數。這個時候2*4+8*4+2*4+1*4=52=64,在VC下會再填充至64.
不在調試模式:就隻有上下cookie,8+*=16=16
上下cookie的作用:訓示配置設定的記憶體大小,是以malloc函數約定俗成,在上下cookie辨別了配置設定的大小。由最後一位,1或0來定義
給出去還是取回來。
另外:如果是配置設定一個string中,它實際上隻有一個指針的大小,4位元組。4+32+4+8=48 是以在cookie中的最後兩位,為31,表示
48大小,1給出去。48的十六進制是30
5.構造與析構函數。arry new 與arry delete
在字元串中,是m_data = new char[strlen(cstr)+1],所對應的析構函數應該是調用delete[] m_data;而不是delete m_data;
與第四點中的知識配合,如果我們是動态配置設定一個數組,那麼還會加上一個4位元組的記憶體來表示由多少個元素組成。
也就是說假如Complex* p = new Complex[3];建立一個數組,三個複數,那麼在VC的調試模式下記憶體大小如下:
8(兩個cookie)+32+4 (這是調試下的debugger Header 與no man land)+8*3 (三個複數元素有六個double)+4(用于表示有幾個元素)
= 72=80 cookie 為51h。
字元串的情況也一樣,加入String* p = new String[3];就會有三個4位元組的指針,加一個4位元組的元素數以及cookie與debugger
arrynew要搭配arrydelete。不然會造成記憶體洩露,這種情況的記憶體洩露是:拿string舉例子,如果是delete[] p;在第三點中有說過,delete由兩個動作組成
那麼arry delete會調用三次dtor,将這一整塊數組删除。
但是如果使用delete p;的話,編譯器不會知道你要删除的是數組,是以它不會調用三次析構函數,連結上面的例子,編譯器以為下面隻有一個,
隻調用一次析構函數。是以它隻回收了第一個指針指向的記憶體空間,第二個第三個指針指向的記憶體,就洩露,記住是指向的記憶體,指針的記憶體就不會洩露。
如果是複數,因為複數裡面沒有指針,是以就算複數沒有些arry delete也不會造成危險。
但是養成一個好習慣,就arrynew一定對應arrydelete。