目录
1.1.1 代码区——存放CPU执行的机器指令,也就是二进制代码。
1.2.2 堆区:由程序员申请释放,或者程序结束操作系统进行回
C++程序在执行的时候,将内存空间大致分为了4大区域
- 代码区:是用来存放编译之后的二进制代码,有操作系统管理,我们不需要操心。
- 全局区:存放全局变量和静态变量以及常量,程序结束销毁
- 栈区:用来存放局部变量,函数栈帧,函数形参,编译器自动申请释放
- 堆区:存放由程序员申请的内存空间,由程序员释放,程序结束操作系统也会进行释放
分成四大区域之后有什么意义呢?
不同的区域存放不同的数据,给了这些区域不同的生命周期,提高了编程的灵活性。
1.1 程序运行前
程序编译成功以后,会生成一个exe可执行文件,还没有双击可执行文件之前就只有两个区域
1.1.1 代码区——存放CPU执行的机器指令,也就是二进制代码。
代码区的特点:
- 共享:共享的目的是对于频繁调用的程序只需要在内存有一份代码就行,不需要调用一次就存一次
- 只读:防止程序意外修改了指令
1.1.2 全局区——存放全局变量、静态变量、部分常量
#include <iostream>
using namespace std;
int g_a = 10;//全局变量
int g_b = 10;
const int c_g_a = 10;
const int c_g_b = 10;
int main()
{
int a = 10;
int b = 10;
cout << "局部变量a:" << (int)&a << endl;
cout << "局部变量a:" << (int)&b << endl << endl;
const int c_l_a = 10;
const int c_l_b = 10;
cout << "const修饰的局部常量c_l_a:" << (int)&c_l_a << endl;
cout << "const修饰的局部常量c_l_b:" << (int)&c_l_b << endl << endl;
cout << "全局变量g_a:" << (int)&g_a << endl;
cout << "全局变量g_b:" << (int)&g_b << endl << endl;
static int s_a = 10;
static int s_b = 10;
cout << "静态变量s_a:" << (int)&s_a << endl;
cout << "静态变量s_b:" << (int)&s_b << endl << endl;
cout << "const修饰的全局常量c_g_a:" << (int)&c_g_a << endl;
cout << "const修饰的全局常量c_g_b:" << (int)&c_g_b << endl << endl;
cout << "字符串常量 1:" << (int)&"abcdef" << endl;
cout << "字符串常量 2:" << (int)&"azxcvbn" << endl << endl;
return 0;
}
输出结果:
1.2 程序运行之后
1.2.1 栈区:存放局部变量、函数栈帧、函数形参
栈区由编译器自动分配和释放,存放局部变量、函数栈帧、函数形参
void Test01(int a)//传入的形参a存放在栈区
{
int l_a = 10;//局部变量存放在栈区
printf("hello world");
}
int main()
{
Test01(10);//函数调用会在栈上开辟函数栈帧
return 0;
}
注意!不要返回局部变量的地址。
int* Test01(int a)
{
int l_a = a;
return &l_a;
}
int main()
{
printf("开始打印:");
int* p = Test01(10);
return 0;
}
调试结果:
发现使用指针p接收的并不是局部变量l_a的地址,这是因为Test01函数在调用的时候在栈区创建了属于自己的函数栈帧用来维护函数Test01、创建局部变量等。当Test01函数结束的时候,函数栈帧销毁,里面维护的局部变量也都还给操作系统。这时候局部变量l_a的地址已经不属于我们了,我们就形成了非法访问。
1.2.2 堆区:由程序员申请释放,或者程序结束操作系统进行回收
在C++中主要使用new在堆上开辟内存,让程序员进行控制
语法:数据类型* 名称 = new 数据类型(变量初识值),初始值可有可无
int main()
{
int* p = new int(10);
cout << *p << endl;
return 0;
}
堆区的数据利用new关键字进行开辟内存