9 内存分区模型
C++程序在执行时,将内存大方向划分为4个区域:
- 代码区:存放函数体的二进制代码,由操作系统进行管理
- 全局区:存放全局变量、静态变量和常量,程序执行结束后由操作系统释放
- 栈区:存放函数的参数值、局部变量等,由编译器自动分配释放
- 堆区:由程序员分配和释放,若程序员不释放,程序执行结束时由操作系统回收
全局变量、局部变量、静态变量、常量的区别
-
全局变量:定义于函数体之外,在全局范围内起作用
-
局部变量:定义于函数体之内,在函数内部起作用
-
静态变量:普通变量(全局、局部)前加 static 后即为静态变量
-
常量:分为字符串常量和const修饰的变量两种
- 字符串常量:使用 “ ” 括起来的均为字符串常量,可直接做取地址&操作,分为全局字符串常量和局部字符串常量,其中局部字符串常量存于栈区
- const修饰的变量:分为const修饰的全局变量和const修饰的局部变量两种,其中const修饰的局部变量存于栈区
int global_val; static int static_global_val; const int const_global_val = 1; string global_string = "helloworld"; int main() { int local_val; static int static_local_val; const int const_local_val = 1; string local_string = "helloworld"; cout << "& global_val = " << &global_val << endl; cout << "& static_global_val = " << &static_global_val << endl; cout << "& const_global_val = " << &const_global_val << endl; cout << "& static_local_val = " << &static_local_val << endl; cout << "& global_string = " << &global_string << endl; cout << "& local_val = " << &local_val << endl; cout << "& const_local_val = " << &const_local_val << endl; cout << "& local_string = " << &local_string << endl; system("pause"); return 0; } /***************** 输出结果 *****************/ & global_val = 00007FF7E72554C0 // 全局变量 & static_global_val = 00007FF7E72554C4 // 静态全局变量 & const_global_val = 00007FF7E7250CC0 // const修饰的全局变量 & static_local_val = 00007FF7E72554F0 // 静态局部变量 & global_string = 00007FF7E72554C8 // 全局字符串常量 & local_val = 000000155FF0F924 // 局部变量 & const_local_val = 000000155FF0F944 // const修饰的局部变量 & local_string = 000000155FF0F968 // 局部字符串常量由以上实例可以看出:
全局进全局区、局部进栈区、static都全局
数据类型 存于全局区 存于栈区 普通变量 全局变量 局部变量 const修饰的变量 const修饰的全局变量 const修饰的局部变量 字符串常量 全局字符串常量 局部字符串常量 静态变量(static修饰的变量) 静态全局变量、静态局部变量 —
const 与 static 区别
1.const关键字:用于修饰变量,使该变量变为只读的常量,被const修饰的变量不能作为左值
2.static关键字:用于声明静态成员变量、静态成员函数、静态局部变量、静态全局变量:
9.1 程序运行前
在程序编译后,生成了exe可执行程序,在未执行该程序前分为两个区域
代码区:
1.存放CPU执行的机器指令
2.代码区的特性:共享、只读
全局区:
1.包含全局变量、静态变量、常量区、字符串常量、由const修饰的变量
2.该区域的数据在程序结束后由操作系统释放
9.2 程序运行后
栈区:
1.在32位系统(x86)中,不要返回局部变量的地址,因为“局部变量存放于栈区,栈区的数据在函数执行完后会自动释放”
int* return_add() { // 一个返回局部变量地址的函数
int a = 10;
return &a;
}
int main() { // 主函数调用上述函数,并打印两次该局部变量地址中的值
int* p = return_add();
cout << *p << endl;
cout << *p << endl;
system("pause");
return 0;
}
/***************** 输出结果(32位系统) *****************/
10
1420929264
/***************** 输出结果(64位系统) *****************/
10
10
解释:32位系统会为局部变量自动保留一次值,所以第一次打印该地址中的值时显示正确;第二次被释放
堆区:
1.使用new关键字进行内存开辟,格式为:数据类型关键字 * 变量名 = new 数据类型关键字(初始值)。其中new 数据类型关键字(初始值)得到的是该堆区的首地址。
2.使用delete关键字进行内存释放,格式为:delete 堆区地址指针
3.创建和释放堆区数组:创建时的格式为:数据类型关键字 * 变量名 = new 数据类型关键字[元素个数]
释放时的格式为:delete[] 堆区地址指针
#include<iostream>
using namespace std;
int* return_add() { // 开辟一个堆区内存空间,数据类型为int,返回该堆区的首地址
int* a = new int(10);
return a;
}
int main() {
int* p = return_add(); // 堆区内存开辟
cout << *p << endl;
cout << *p << endl;
delete p // 堆区内存释放
cout << *p << endl; // 此行代码会报错,因为释放掉堆区内存后,就不允许再次访问这部分“未被开辟的堆区空间”
system("pause");
return 0;
}
/***************** 输出结果(32位系统) *****************/
10
10 // 与之前的结果进行对比,可以看出本次32位系统由于将10保存在堆区,连续打印不会乱码

被折叠的 条评论
为什么被折叠?



