c++内存分区/超全,超详细

C++程序在执行时,将内存大方向划分为4个区域(这四个区域是不可用肉眼看见的,是存在于内存条上的)

代码区:存放函数体的二进制代码,由操作系统进行管理的·

全局区:存放全局变量和静态变量以及常量·

栈区:由编译器自动分配释放,存放函数的参数值(形参),局部变量等·

堆区:由程序员分配和释放,若程序员不释放程序结束时由操作系统回收


程内存分区的意义:不同区域存放的数据,赋予不同的生命周期,给我们更大的灵活编


1程序运行前

在程序编译后,生成了exe可执行程序,未执行该程序前分为两个区域

代码区:

存放CPU执行的机器指令

代码区是共享的,目的是对于频繁被执行的程序,只需要在内存中有一份代码即可

代码区是只读的,使其只读的原因是防止程序意外地修改了它的指令

全局区:全局变量和静态变量存放在此.

全局区还包含了常量区,字符串常量和其他常量也存放在此,该区域的数据在程序结束后由操作系统释放

bc:写在函数体内部的变量都是局部变量

在局部变量的数据类型前加上static,会变成静态变量。局部变量变成全局变量会延长生命周期,程序结束后由系统释放。

2程序运行后

栈区:由偏译器自动分配释放存放函故的参放值局部变量等

注意事项:不要返回局部变量的地址,栈区开辟的数据由编泽器自动释放

输出两次*p;第一次输出10,第二次输出一堆乱码。

执行完函数func,编译器保留数据一次后,数据就自动释放了。

堆区:由程序员分配释放,若程序员不释放,程序结束时由操作系统回收

在C++中主要利用neW在堆区开辟内存

利用new关键字可以即将变量的数据开辟到堆区

#include <iostream>
using namespace std;
int* func()
{	//new关键字可以将数据开辟到堆区
	int* p = new int(10);
	/*如果要开辟整形数据就用int,int后边小括号里是数据的初始值
	然后new关键字将数据的地址返回,用一个指针*p接收*/
	return p;//p代表的是数据p的地址
}

int main()
{
	int* p = func();
	cout << *p << endl;//输出10;
}

指针int*p本质上是一个局部变量,存放在栈区,但是指针*p指向的地址就是堆区中数据10的地址。

3、new操作符

C++中利用new操作符在堆区开辟数据

堆区开辟的数据,由程序员手动开辟,手动释放,释放利用操作符delete

语法:new 数据类型

利用new创建的数据,会返回该数据对应的类型的指针

#include <iostream>
using namespace std;
int* func()//new的基本用法
{
	int* p = new int(10);//在堆区创建整形数据
	return p;//返回的是该数据类型的指针
}
void test01()
{
	int* p = func();
	cout << *p << endl;
	/*堆区的数据,由程序员管理开辟和释放
	如果想释放堆区的数据,用关键字delete*/
	delete p;
	//这个时候,已经把堆区的数据释放了,从这个地方开始,堆区没数据了
	/*这个时候,如果再来一个“cout<< *p<<endl;”
	会报错,因为数据被释放了,没有权限访问了
	在访问就属于非法访问*/
}
void test02()//在堆区开辟数组
{
	//在堆区创建存有10个整型数据的数组,不是变量
	//返回的是这段连续内存空间的首地址
	int* arr = new int[10];
	for (int i = 0; i < 10; i++)
	{
		arr[10] = i + 100;//给数组赋值,分别是100~109;
	}
	for (int i = 0; i < 10; i++)
	{
		cout<<arr[10] << endl;
	}
	//释放堆区数组的时候要加一个中括号
	delete[] arr;
}
int main()
{
	test01();//输出10;
	test02();//输出数组
}

释放了堆区数据后,有输出这个数据,会报错,因为数据被释放了,没有权限访问了。

就像这样:

数组的情况类似。

经验分享 程序员 微信小程序 职场和发展