首页 > 系统相关 >C++之内存四区

C++之内存四区

时间:2024-08-16 12:52:22浏览次数:9  
标签:常量 int 四区 代码 C++ 内存 new 堆区

目录

一、内存四区

在计算机科学中,特别是在c或c++语言编程时,内存通常大致分为四个区域,而不同的区域存放的数据赋予不同的生命周期,给我们更大的灵活编程:

  1. 代码区:存储程序的可执行代码(二进制代码),也就是程序编译后的机器指令,通常是只读,防止运行时意外修改指令
  2. 全局区(数据区):存放全局变量和静态变量以及常量,这个区域在程序启动时被初始化,并且具有固定的内存分配
  3. 栈区:由编译器自动分配释放,存放函数调用时的局部变量、函数参数、返回地址等等,并且每次函数调用时栈都会增长,函数返回时,栈会收缩
  4. 堆区:堆区是程序运行时动态分配内存的区域,由程序员分配和释放,如果程序员不释放,程序结束时由操作系统回收

二、程序运行前

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

  • 代码区:
  1. 存放cpu执行的机器指令(二进制代码)
  2. 代码区是共享的,共享的目的是对于频繁被执行的程序,只需要在代码中有一份代码即可
  3. 代码区是只读的,使其只读的原因是防止程序意外地修改了它的指令
  • 全局区(数据区):
  1. 全局变量和静态变量存放在此
  2. 全局区还包含了常量区,字符串常量和其他常量也存放在此
  3. 该区域的数据在程序结束后由操作系统回收

代码验证全局区:

int main()
{
	//静态变量
	static int a3;
	static int b3;
	//局部变量
	int a4;
	int b4;
	//局部常量
	const int a5=10;
	const int b5=10;
	//打印地址
	cout << "全局变量a1的地址:" << (int)&a1 << endl;
	cout << "全局变量b1的地址:" << (int)&b1 << endl;
	cout << "全局常量a2的地址:" << (int)&a2 << endl;
	cout << "全局常量b2的地址:" << (int)&b2 << endl;
	cout << "静态变量a3的地址:" << (int)&a3 << endl;
	cout << "静态变量b3的地址:" << (int)&b3 << endl;
	cout << "局部字符串常量a6的地址:" << (int)&"hello" << endl;
	cout << "局部字符串常量b6的地址:" << (int)& "hello" << endl;
	cout << "局部变量a4的地址:" << (int)&a4 << endl;
	cout << "局部变量b4的地址:" << (int)&b4 << endl;
	cout << "局部常量a5的地址:" << (int)&a5 << endl;
	cout << "局部常量b5的地址:" << (int)&b5 << endl;	
}
结果:
全局变量a1的地址:-868223152
全局变量b1的地址:-868223148
全局常量a2的地址:-868238320
全局常量b2的地址:-868238316
静态变量a3的地址:-868223144
静态变量b3的地址:-868223140
局部字符串常量a6的地址:-868238312
局部字符串常量b6的地址:-868238312
局部变量a4的地址:-1634731644
局部变量b4的地址:-1634731612
局部常量a5的地址:-1634731580
局部常量b5的地址:-1634731548

根据结果显示的地址距离不难发现全局区存放有:全局变量、静态变量(static修饰)、常量(字符串常量、全局常量(const修饰)),而局部变量和局部常量(const修饰)都不在全局区中

总结:

  • c++中在程序运行前分为全局区和代码区
  • 代码区特点是共享和可读
  • 全局区中存放全局变量、静态变量、常量
  • 常量区中存放const修饰的全局常量和字符串常量

三、程序运行后

栈区:

  • 由编译器自动分配释放,存放函数的形参、局部变量、返回地址等
  • 注意事项:不要返回局部变量的地址,栈区开辟的数据由编译器自动释放

代码举例:

int* func(int a)//形参
{
	int b = a;//局部变量
	return &b;//返回地址
}
int main()
{
	int*p =func(10);
	cout << *p << endl;
	cout << *p << endl;
}
结果:
10
2297916

由前文知func函数中的数据都在栈区当中,当这个函数执行结束之后内存就自动释放了,但是编译器会对返回的地址会做一次保留,所以第一次输出时就是10,但是第二次就是一个随机值了,所以证明了不能返回局部变量的地址,这会造成野指针的问题

堆区:

  • 由程序员分配和释放,如果程序员不释放,程序结束时就由操作系统回收
  • 在c++中主要利用new关键字在对堆区开辟空间

代码举例:

int* func(int a)//形参
{
	//利用new关键字将数据开辟到堆区
	//这里的指针p本质也是局部变量,放在栈上,但是指针保存的数据是放在堆区的,所以返回的值也是在堆区
	int *p=new int(a);
	return p;//返回地址
}
int main()
{
	int*p =func(10);
	cout << *p << endl;
	cout << *p << endl;
}

四、new操作符

在c++中,主要用new操作符在堆区开辟空间,堆区开辟的数据由程序员手动开辟和释放,而释放就要利用操作符delete,利用new 创建的数据会返回一个指向该数据类型的指针(地址),下面是代码介绍语法:

class p//定义类
{
	public:
	p()
	{
		cout<<"默认构造函数的调用"<<endl;
	}
	~p()
	{
		cout<<"析构函数的调用"<<endl;
	}
}
int main()
{
	//分配单个对象
	int* p1 = new int;//在堆分配一个int类型的内存并返回其指针
	//分配数组
	int* arr = new int[10];//分配一个包含10个整型的数组
	//初始化对象
	int* p2 = new int(5);//利用new开辟空间时可以顺便初始化整型为5
	//分配并构造对象
	p* p3=new p();
	//释放内存
	delete p1;
	delete p2;
	delete []arr;
	delete p3;
}

注意事项:

  • 每次调用new操作符都应该有一个对应的delete或delete[]操作符来释放内存
  • 忘记释放内存将会导致内存泄漏
  • 注意区分分配数组和单个对象的区别,并且在释放内存时也有所区别

标签:常量,int,四区,代码,C++,内存,new,堆区
From: https://blog.csdn.net/2303_80883523/article/details/141256822

相关文章

  • Centos 服务器系统内存故障排查
    该笔记主要记录一下如何排查指定服务器中的指定内存条是否损坏。1.内存故障排查因为68–71软SBC服务器都是Centos7系统,所以我们可以通过以下命令来排查内存是否出现损坏。grep"[0-9]"/sys/devices/system/edac/mc/mc*/csrow*/ch*_ce_count1>count不为0表示有错误2>mc......
  • SSM-国外鞋服代购平台-97782(免费领源码+开发文档)可做计算机毕业设计JAVA、PHP、爬虫、
    SSM国外鞋服代购平台摘 要随着科学技术的飞速发展,社会的方方面面、各行各业都在努力与现代的先进技术接轨,通过科技手段来提高自身的优势,鞋服代购平台当然也不例外。代购平台是以实际运用为开发背景,运用软件工程原理和开发方法,采用Java技术构建的一个管理系统。整个开发过......
  • C++ string类型常用操作
    string类型操作字符串切割str.substr(索引,切割的个数) -> 返回字符串注意:第二个参数为切割的个数stringbuf="abcdefg";buf.substr(0,2);//结果为"ab"buf.substr(1,3);//结果为"bcd"字符串输入使用getline读入字符串可以保留字符串中的空格 getline(cin......
  • 小学生教你微积分,用编程理解高数(python,C,C++)
    一、代码实现微分(实际上是导数,微分不用除dx):python代码:x=0dx=0.00001deff(x):y=2*xreturnyprint((f(x+dx)-f(x))/dx)C语言代码:#include<stdio.h>doublex=1;doubledx=0.00001;doublef(doublearg){doubley=2*arg;returny;}......
  • 指针:存放内存地址的变量
    //指针:类型跟存放变量的类型一致定义格式:数据类型*变量名;static关键字可以防止内存被释放禁止使用野指针和悬空指针特殊指针:void*p;空类型指针,可以存放任何类型指针,但是不能进行操作//指针高级应用:以字节为单位,交换两个变量的值#include<stdio.h>voidSwap(void*p1,void*......
  • 动态内存分配
    在堆中开辟空间malloc:申请连续空间calloc:申请空间且初始化数据realloc:修改空间大小free:释放空间open:打开文件close:关闭文件......
  • 华为OD笔试机试 - 攀登者2 (python/c++/java 2024年C卷D卷真题算法)
    华为OD机试(C卷+D卷)2024真题目录(Java&c++&python)题目描述攀登者喜欢寻找各种地图,并且尝试攀登到最高的山峰。地图表示为一维数组,数组的索引代表水平位置,数组的元素代表相对海拔高度。其中数组元素0代表地面。例如:[0,1,2,4,3,1,0,0,1,2,3,1,2,1,0],代表如下图所示的......
  • 编程基础题:开关灯(C语言方式代码,C++方式代码,Python3方式编写)三种语言编写代码
    1.题目描述:假设有N蓋灯(N为不大于5000的正整数),从1到N按顺序依次编号,初始时全部处于开启状态;第一个人(1号)将灯全部关闭,第二个人(2号)将编号为2的倍数的灯打开,第三个人(3号)将编号为3的倍数的灯做相反处理(即,将打开的灯关闭,将关闭的灯打开)。依照编号递增顺序,以......
  • C语言 ——— 结构体内存对齐
    目录发现问题 偏移量宏:offsetof()结构体内存的对齐规则小结 发现问题有以下两个结构体:结构体1:structS1{ charc1;//1字节 inti;//4字节 charc2;//1字节};结构体2:structS2{ charc1;//1字节 charc2;//1字节 inti;//4字节};通常情况下......
  • C++快速幂
    快速幂算法是一种用于快速计算幂运算(即 ab)的算法,其中 a 是底数,b 是指数。它的主要思想是减少乘法运算的次数,通过将指数 b 分解为二进制形式并利用幂的运算法则来加速计算过程。以下是一个使用C++实现的快速幂算法的例子,它既可以处理正整数幂的情况,也可以稍微修改以处理......