内存四区
这篇文章主要介绍的是程序内存的四个存储区域:代码区、全局区、栈区、堆区。
代码区
代码区,简单来说就是存放代码的一块区域,这块区域在程序运行前存在。其实代码区存放的代码时CPU执行的机器指令,也就是二进制字符串。
代码区有两个特点:共享性和只读性。
1、共享性:因为一个程序有可能被运行很多次,不可能每次运行前都要将代码保存一次,所以共享性是为了让程序能够高效的多次运行。
2、只读性:为了防止程序运行过程中被恶意修改代码,造成损失,所以代码区具有只读性,不能修改。
全局区
全局区也是在程序运行之前存在的一块区域。存放在全局区的数据主要有三类:全局变量、静态变量、常量。其中常量有可以细分为字符串常量和const修饰的变量,字符串常量存放在全局区。const修饰的变量又可以分为const修饰的全局变量和const修饰的局部变量。其中const修饰的全局变量存放在全局区,而const修饰的局部变量(局部常量)不存放在全局区。下面代码演示
#include<iostream>
using namespace std;
//全局变量
int g_a = 10;
int g_b = 100;
//const修饰的全局变量
const int c_g_a = 10;
const int c_g_b = 100;
int main()
{
//静态变量
static int s_a = 100;
static int s_b = 10;
//const修饰的局部变量
const int c_l_a = 100;
const int c_l_b = 10;
//全局变量
cout << "全局变量g_a的地址为:" << &g_a << endl;
cout << "全局变量g_b的地址为:" << &g_b << endl;
//静态变量
cout << "静态变量s_a的地址为:" << &s_a << endl;
cout << "静态变量s_a的地址为:" << &s_a << endl;
//字符串常量
cout << "字符串常量的地址为:" << &"hello" << endl;
//const修饰的全局变量
cout << "const修饰的全局变量的地址为:" << &c_g_a << endl;
cout << "const修饰的全局变量的地址为:" << &c_g_a << endl;
//const修饰的局部变量
cout << "const修饰的局部变量的地址为:" << &c_l_a << endl;
cout << "const修饰的局部变量的地址为:" << &c_l_a << endl;
}
从运行结果可以看出全局变量、静态变量、字符串常量、以及const修饰的全局变量他们的内存位置靠得非常近,而const修饰得局部变量与他们靠得非常远。这也就说明了const修饰得局部变量与另外几个不在一个区域。
另外:全局区的数据在程序结束后由系统释放
栈区
栈区由编译器自动释放,存放在栈区的数据主要有函数的参数、和局部变量。尤其需要注意的是不能返回局部变量的地址,因为栈区的数据在程序结束后是由编译器自动释放,所以返回局部变量的地址是找不到你想找的那个数据的。
#include<iostream>
using namespace std;
int* test01()
{
int a = 10;
int* p = &a;
return p;
}
int main()
{
int* p = test01();
cout << *p << endl; //第一次成功访问到数据是因为编译器做了一次保留
cout << *p << endl; //第二次就访问不到该数据了
}
堆区
堆区的数据由程序员进行释放,当然如果程序员忘记释放,在程序运行结束后编译器也会帮你释放。一般在堆区开辟空间需要用到new关键字。
在上面的栈区说到不能返回局部变量的地址是因为局部变量存放在栈区,栈区的数据由编译器自动释放。那么我们把数据开辟到堆区呢?
#include<iostream>
using namespace std;
int* test02()
{
int* p =new int (10);
return p;
}
int main()
{
int* p = test02();
cout << *p << endl;
cout << *p << endl;
cout << *p << endl;
cout << *p << endl;
}
可以发现输出了四次仍然可以访问到数据。这是因为堆区的数据没有被释放,那么释放之后又会如何呢?
#include<iostream>
using namespace std;
int* test02()
{
int* p =new int (10);
return p;
}
int main()
{
int* p = test02();
cout << *p << endl;
cout << *p << endl;
free(p);
cout << *p << endl;
cout << *p << endl;
}
可以看到,前两次是没有将数据释放掉是可以访问的,后面将数据释放掉之后,就访问不到该数据了。
以上就是我对内存四区的全部理解,如果有不足的地方请指正。