一、内存四大区
1、我们把程序执行前后的内存分为四个区:
代码区、全局区、栈区、堆区
2、但是有一个疑问,这样分类的意义是什么?
例如:因为我们在实际编程的时候,需要根据不同的功能需求,会声明不同类型的变量(如全局变量,局部变量,全局常量,字符串常量等),它们拥有不同的长度、生命周期释放方式等。这样就需要存放在不同的内存区域,这样就能提高程序运行效率,更加灵活地编程。
二、内存四区的功能
-
代码区
这个区域存放函数体的二进制代码.是由操作系统进行管理的。 -
全局区
全局区主要是用来存放全局变量和静态常量(即使用static关键字定义的变量)(一般会是字符串常量),里面有细分出一个常量区。要注意局部变量和局部常量是不属于这个区域的。
该区域是在程序结束后由操作系统释放。
如图:全局变量和常量的地址十分相近,都是存放在全局区的,而局部变量的地址也十分相近,但并非在全局区,而是在下面的栈区中。 -
栈区
由编译器自动分配释放,存放函数的形参、局部变量等。当函数执行完毕时自动释放。
如上图所示的局部变量b和c就是存放在栈区的,这两个变量是定义在main函数的,所以是当整个程序执行完,系统才释放空间。如果是定义在自己声明的其他函数体内,当该函数执行完毕之后其内存即被释放。
值得一提的是,查看局部变量的地址,这样的操作是不正确的,看下面一段代码和输出:
main函数里面有两句完全相同的输出,但终端输出时缺发现只有第一次输出是正确的,其实是因为a是局部变量,在test函数执行后就会被释放,但是编译器为其保留了一次操作的余地,这次操作之后就会被释放了。所以第二次输出的值是不正确的。 -
堆区
一般由程序员手动分配释放(动态内存申请与释放),若程序员不释放,程序结束时可能由操作系统回收。与栈区最大的区别就是,堆区的变量都是我们自己分配和释放的。在学习C语言的时候我们学习了动态内存分配函数malloc,以及其释放函数free。在C++中,起到相同功能的是函数new和delete,它们具体的用法如下:
int *p=new int(10); //为单个变量申请内存空间,其存放的地址为10
int *p=new int [10]; //为数组申请内存空间,其中指针P指向数组的首地址
delete (p);
运行下面的程序:
#include <iostream>
#include <string>
using namespace std;
int * test_1()
{
int *p=new int(10);
return p;
}
int * test_2()
{
int *array=new int[10];
for(int i=0;i<10;i++)
{
array[i]=i;
}
return array;
}
int main()
{
int *p=test_1();
int *array=test_2();
cout<<"a的值为:"<<*p<<endl;
cout<<"a的值为:"<<*p<<endl;
delete(p);
cout<<"a的值为:"<<*p<<endl;
for(int i=0;i<10;i++)
{
cout<<"数组的第"<<i<<"个元素的值为:"<<array[i]<<endl;
cout<<"数组的第"<<i<<"个元素的值为:"<<array[i]<<endl;
}
delete(array);
for(int i=0;i<10;i++)
{
cout<<"数组的第"<<i<<"个元素的值为:"<<array[i]<<endl;
}
system("pause");
}
显然,使用new为局部变量申请地址之后,即使重复访问地址,变量的值也不会丢失,就是因为使用new申请的变量地址存放到堆区了。再使用delete函数释放了变量的内存空间,所以再次访问时发现变量的值已丢失。