侯捷C++手把手教學:堆、棧與記憶體管理

weixin_39770712發表於2020-10-07

所謂stack(棧),所謂heap(堆)
Stack:是存在於某作用域(scope)的一個記憶體空間(memory space)。例如當你呼叫函式,函式本身即會形成一個stack用來放置它所接收的引數,返回地址,及區域性物件(local object)。
Heap:或稱system heap,是指由作業系統提供的一塊global記憶體空間,程式可動態分配(dynamic allocated)從中獲得若干區域(blocks)。
stack objects的生命期

class Complex  { ... };
...

{
    Complex c1(1,2);
}

c1便是所謂stack object,其生命在作用域(scope)結束之際結束。
這種作用域內的object,又稱為auto object,因為它會被自動清理。
static local objects的生命期

class Complex  { ... }
...

{
    static Complex c2(1,2);
}

c2便是所謂static object,其生命在作用域(scope)結束之後仍然存在,直到整個程式結束。
global objects的生命期

class Complex  { ... };
...
Complex c3(1,2);

int main()
{
    ...
}

c3便是所謂global object,其生命在整個程式結束之後才結束。也可以把它視為一種static object,其作用域是整個程式。
heap objects的生命期
正確寫法:

class Comliex  { ... };
...

{
    Complex* p = new Complex;
    ...
    delete p;
}

p所指的便是heap object,其生命在它被delete之際結束。
錯誤寫法:

class Complex  { ... };
...

{
    Complex* p = new Complex;
}

以上出現記憶體洩漏(memory leak),因為當作用域結束,p所指的heap object仍然存在,但指標p的生命卻結束了,作用域之外再也看不到p。
new:先分配memory,再呼叫ctor

Complex* pc = new Complex(1,2);

編譯器轉換為:

Complex *pc;
void* mem = operator new( sizeof(Complex) );  //分配記憶體,其內部呼叫malloc(n)
pc = static_cast<Complex*>(mem);  //轉型
pc->Complex::Complex(1,2);  //建構函式

delete:先呼叫dtor,再釋放memory

String* ps = new String("Hello");
...
delete ps;

編譯器轉化為:

String::~String(ps);  //解構函式,釋放指標所指的空間
operator delete(ps);  //釋放記憶體,釋放指標;內部呼叫free(ps)

記憶體管理
作業系統&最後一位為0,則表示可以回收,可以覆蓋使用;為1的話就不能覆蓋。
array new一定要搭配array delete。
delete[] p和delete p的區別:
會影響解構函式的呼叫次數,對於包含指標的類,不呼叫解構函式則指標所指向的記憶體空間沒有得到釋放。
錯誤使用會造成記憶體洩漏,是指標所指向的空間記憶體洩漏。

相關文章