一、栈区(Stack)
栈区用来存储函数的参数值、局部变量的值等数据。栈区是自动分配和释放的,函数执行时会在栈区分配空间,函数执行结束时会自动释放这些空间。栈区的数据是连续分配的,由系统自动管理。
注意事项:不要返回局部变量的地址,栈区开辟的数据由编译器自动释放
输出局部变量的地址编译器会报上述错误。
报错原因:
代码示例:如果连续输出局部变量的值,会如何输出?
#include <iostream>
using namespace std;
int *func()
{
//在栈区中创建局部变量
int a = 10;
int *ptr = &a;
//返回局部变量的地址
return ptr;
}
int main()
{
//调用函数,接收返回值
int *p = func();
cout<<*p<<endl;
//局部变量只能返回一次,返回后栈区开辟的数据由编译器自动释放。
cout<<*p<<endl;
return 0;
}
运行结果:
10
0
二、堆区(Heap)
堆区用来存储动态分配的内存,程序员可以通过new
和delete
关键字来手动分配和释放堆区的内存。堆区的数据是不连续分配的,由程序员手动管理。
注:内存由程序员分配释放,若程序员不释放,程序结束时由操作系统回收
代码示例:使用new和delete创建和释放堆内存,如果程序员不手动释放或者程序没有运行结束,堆内存数据不会自动释放。
#include <iostream>
#include <stdio.h>
using namespace std;
int *func()
{
//使用new关键字,可以将数据开辟到堆区
int *p = new int(10);
//返回局部变量的地址
return p;
}
int main()
{
//调用函数,接受返回值
int *p = func();
cout<<*p<<endl;
cout<<*p<<endl;
//指针地址
cout<<p<<endl;
delete p;
//访问到的数据已经被覆盖,或者操作系统已经回收了这块内存等等
//这种情况可能会打印出数据,但这是不安全的,不应该依赖这种行为。
cout<<*p<<endl;
cout<<p<<endl;
return 0;
}
运行结果:如果程序员不手动释放或者程序没有运行结束,堆内存数据不会自动释放。
10
10
0x1041620
17063904
0x1041620
创建堆内存后,会在栈里自动保存一个指针地址*p,指向堆内存地址0x7....。
三、全局/静态存储区(Global/Static Storage)
全局变量和静态变量存储在全局/静态存储区中。全局变量在程序整个执行过程中都存在,静态变量在程序生命周期内存在,但只能在定义它的函数或文件内访问。
四、代码区(Code)
代码区存储程序的执行代码,是只读的。
以上就是C++中常见的内存分区模型,理解内存分区模型对于理解内存管理和指针操作非常重要。