堆、栈与内存管理

    C++的内存区域分为五个区,分别是自由存储区全局/静态存储区常量存储区

    (1)Stack(栈),是存在于某作用域(scope)的一块内存空间(memory space)。例如当你调用函数,函数本身即会形成一个stack用来放置它接收的参数,以及返回的地址。在函数本体内声明的任何变量,其所使用的内存块都取自上述stack。

   (2)Heap(堆),或称system heap,是指由操作系统提供的一块global内存空间,程序可由new动态分配(dynamic allocated)从某获得若干区块(blocks)。

    (3)自由存储区,是由malloc等分配的内存块,和堆十分相似,用free来释放。

    (4)全局/静态存储区,全局变量和静态变量被分配到同一块内存中(在C语言中,全局变量又分为初始化的和未初始化的,在C++中则没有这一区分)。

    (5)常量存储区,这是一块特殊存储区,里面存放常量,不允许被修改。

    堆和自由存储区可以看做是同一块区域,new底层实现代码中调用malloc,new可以看做是malloc智能化的高级版本。堆和栈在内存中的生长方向是相反的,栈的生长方向是向下的,即向着内存地址减小的方向增长;而堆的生长方向是向上的,向着内存地址增加的方向增长。

    下面通过例子,来理解一下具体概念:

class Complex (...);
...
{
  Complex c1(1,2);
  Complex* p = new Complex(3);
}

c1所占的空间来自stack。Complex(3)是个临时对象,其所占用的空间是以new自heap动态分配而得的,并由指针p指向。

char *p1 = "123456";
char *p2 = (char *)malloc(10);
指针p1和p2本身存于栈中,p1所指对象存于常量存储区,p2所指对象存于堆中。

    stack objects的生命期

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

c1便是stack object,其生命在作用域结束之际结束,这种作用域内的object,又称为auto object,因为它会被自动清理(析构函数会被自动调用)。

    static local objects的生命期

class Complex {...};
...
{
  static Complex c2(1,2);
}

c2便是static object,其生命在作用域结束之后仍然存在,直到整个程序结束。

    global objects的生命期

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

int main()
{
  ...
}

c3便是global object(在任何大括号之外的变量),其生命在整个程序结束之后才结束。也可以把它视为一种static object,其作用域是整个程序。

    heap objects的生命期

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

p所指的便是heap object,其生命在它被delete之际结束。如果没有delete p语句,就会出现内存泄露,因为当作用域结束,p所指的heap object仍然存在,但指针p的生命却结束了,作用域之外再也看不到p(也就没有机会delete p)。

    new是先分配内存,再调用构造函数;而delete是先调用析构函数,再释放内存。




猜你喜欢

转载自blog.csdn.net/susu0203/article/details/79796263