C/C++中程序数据的分类与内存分布,C++内存管理方式之new / delete 操作符与malloc / free的区别

news/2024/10/18 14:16:26/

TIPS

  1. const修饰数据类型并不会影响它在内存当中某个区域的存储位置,比方说原先是在栈区上面的,然后用const修饰了一下,并不就是说你现在已经变到静态区里面去了,你还是在栈上面
  2. 指针与指针之间的等号赋值也需要考虑到权限的放大与缩小问题,bty,地址等于指针。也就是说从右往左的过程当中,权限只能够平移或者缩小,权限不能够放大。

C/C++中程序数据的分类与内存分布

在这里插入图片描述

  1. 在程序当中需要存储一些数据,然后数据的分类有局部数据,还有就是静态数据和全局数据,他们的特点就是生命周期在全局可以一直用,还有常量数据和动态申请的数据。
  2. 在平时写程序的过程当中,局部数据用的最多,比如说在当前函数当中去创建各种各样的变量,所以说局部数据通常就是在函数里面定义的各种局部变量,他就是跟着函数走,本质上就是存储在函数调用的时候开辟的函数栈帧里面;静态数据与全局数据的话,他们的生命周期就是整个程序存在的时间;常量数据就是不能够去修改的,比如常量字符串等等;然后动态申请的数据基本上在数据结构当中用的会比较多一点.
  3. 然后一般我们在编译器上写程序的话,***我们写的这些代码实际上都是在磁盘里面,因为相当于我们是在文件里面去写代码,所以说我们写的这些东西是在磁盘文件里面,然后对于写的这些代码进行编译加链接,就会生成一个可执行程序,这个可执行程序也是以一个磁盘文件的形式存在于磁盘里面。***然后接下来我们把这个可执行程序给他运行起来,运行起来的本质就是以一个进程的角度在操作系统之上进行运行。
  4. 然后这个可执行程序里面都是一些计算机能够看懂的二进制指令,当然还有一些数据。然后当这个可执行程序运行起来以后,也就是载入到内存当中,这个被可执行程序exe使用的内存区域每个进程呢都把它叫做虚拟进程地址空间。这个进程地址空间就需要对不同数据进行存储,因此就会内部划分区域。最上面的话是高地址,主要是给操作系统的内核用的;然后接下来就是几个熟悉的区域:栈,堆,静态区/数据段,常量区/代码段。
  5. 然后对于局部数据而言,一般都是存在栈上面,比方说要去调用一个函数,那么就会去建立函数栈帧,建立函数栈帧最本质的一个要点就在于需要去存储局部数据。然后到函数结束的时候,函数栈帧销毁,那么里面的这些局部数据也就会一起去销毁。其实局部数据的感觉就有点类似于一次性的那种感觉,就是短期用用的。对于栈区的话还有一个作用就是方便我们去进行递归就是不断的去建立函数栈帧,然后再进行销毁,然后再进行空间的复用(比如说二叉树)
  6. 但有时候的话也需要用一些静态数据全局数据,也就是说随着时间的推移,要能够保持一定的连续性,这些数据的话它不能够存在栈区里面,所以说就需要单独去找一个区域给他存起来,所以说,就在静态区/数据段这个地方把这些数据给他存起来,然后这些数据的话,在整个程序在的时候,他都也都是在的,不是说函数结束它就销毁了。
  7. 然后对于一些常量以及在可执行程序当中的一些指令的话,都是放在常量区/代码段的
  8. 然后还有一些数据,比方是需要程序员他自己要去动态开辟的,并且是自己申请自己释放空间,相当于就是说是自主权比较大一点,对于这种动态申请的数据,它就是放在堆上面
  9. 然后为什么要划分成这么多的区域?主要就是因为我们的程序有很多需求.
    10.在这里插入图片描述
    在这里插入图片描述

经典检测

int globalVar = 1;
static int staticGlobalVar = 1;
void Test()
{
static int staticVar = 1;
int localVar = 1;
int num1[10] = { 1, 2, 3, 4 };
char char2[] = "abcd";
const char* pChar3 = "abcd";
int* ptr1 = (int*)malloc(sizeof(int) * 4);
int* ptr2 = (int*)calloc(4, sizeof(int));
int* ptr3 = (int*)realloc(ptr2, sizeof(int) * 4);
free(ptr1);
free(ptr3);
}

在这里插入图片描述

  1. 这个肯定是个全局变量,全局变量是放在静态区的C
  2. 这个也是一个静态变量,那么他想当然肯定也是放在静态区的C
  3. 这个也是一个静态变量,那么他想当然肯定也是放在静态区的C
  4. 这个的话相当于是一个函数里面的局部变量而已,肯定是在内存栈区里面A
  5. 这个也是一个函数里面的一个数组而已,在函数栈帧里面,所以说也是在内存栈区里面A
    在这里插入图片描述
  6. 这是一个在函数里面的一个数组而已,那么肯定也是在函数栈帧里面,肯定是在内存栈区里面A
  7. 这个char2是一个数组的名字,这就是数组首元素的地址,然后相当于是对数组首元素的地址进行解引用,那不就是相当于是在访问处于内存栈区的数组元素吗?所以说访问出来的东西还是在内存的栈区里面A
  8. 他其实相当于是一个指针,不过这边需要注意,虽然他是const的修饰,但这并不意味着它是一个静态变量了,不意味着他就跑到静态区里面去了。他无非还就是一个内存栈区里面的普通指针罢了,不过有点类似于常变量的这种感觉。然后这个指针变量里面存放的就是这个字符串常量第一个字符的地址。不过指针变量是在栈区的A
  9. 然后对于这个指针变量pchar进行解引用,首先这个指针变量它指向的是处于内存常量区的字符串常量的第一个字符,那么这样子解引用出来就得到了一个字符,这个字符就是处于内存常量区里面的那个字符,所以在常量区D
  10. ptr1无非就是一个指针而已,肯定是在内存栈区的,不过它指向的那块内存空间是属于内存堆区的罢了A
  11. 然后对这个指针ptr1进行解引用操作,这时候访问到的就是属于内存堆区里面的数据,所以在堆区B
    在这里插入图片描述
  12. sizeof数组名,计算的是整个数组所占内存字节大小,所以是40
  13. 这个与第一个道理是一样的,也是计算整个数组所占内存字节的大小,sizeof是计算进入字符串终止符\0的,所以大小为5
  14. 相当于就是统计字符串的长度,然后碰到\0就会停下来,\0的话是不会统计进去的,所以为4
  15. 这个相当于是在计算一个指针的大小,那这个非常简单,在32位机器下面是四个字节
  16. 这个也是在统计字符串的长度,为4,很简单
  17. 这个也是在计算一个指针的大小,也非常简单,就是四个字节(32位下)

C++内存管理方式之new / delete 操作符

  1. 首先复习回顾C,C的那些动态申请内存的各种方法在cpp当中也是可以去使用的
    在这里插入图片描述
  2. C语言内存管理方式在C++中可以继续使用,但有些地方就无能为力,而且使用起来比较麻烦,因此C++又提出了自己的内存管理方式:通过new和delete操作符进行动态内存管理。
  3. 在这里插入图片描述
  4. 如:用new向内存堆区动态申请一个int类型的空间
    在这里插入图片描述
  5. 如:用new向内存堆区动态申请一个int类型的空间并初始化为522
    在这里插入图片描述
  6. 如:用new向内存堆区动态申请10个int类型的空间
    在这里插入图片描述
  7. 注意:申请和释放单个元素的空间,使用new和delete操作符,申请和释放连续的空间,使用new[]和delete[],注意:匹配起来使用,如:
    在这里插入图片描述

new/delete 与 malloc/free 区别

  1. 在C++向内存堆区申请与释放空间的话,一般是用new与delete。然而在C的话用malloc/free。
  2. 然后如果向内存堆区申请的,这块空间是给内置类型来用的,其实这两种方法的话,差距并不是很大,甚至说没有。
  3. 真正体现优劣的地方就在于如果说向内存堆区申请的这块空间是给那些自定义类型变量(实例化对象)的,对于malloc/free来讲,他们只会单纯的去开辟一块多少多少大小的空间,然后等会儿把这块空间给他全部释放掉;但对于new与delete,如果 “自定义类型* p = new 自定义类型(构造函数参数)”, 就像这样子相当于在向内存堆区申请空间的同时,还能够直接进行调用构造函数初始化;然后delete p; 在把这块空间释放前会去调用析构函数。
    在这里插入图片描述

http://www.ppmy.cn/news/64569.html

相关文章

C. Enlarge GCD(内存的限制 + 数组的访问速度)

Problem - C - Codeforces Mr. F 有 n 个正整数 a1,a2,…,an。 他认为这些整数的最大公约数太小了。所以他想通过删除其中一些整数来扩大它。 但是这个问题对他来说太简单了,所以他不想自己做。如果你帮他解决这个问题,他会给你一些奖励分数。 你的任…

【代码随想录】刷题Day20

1.最大二叉树 654. 最大二叉树 这题与中序和后序构造二叉树有点相似 其实思路都是划分区域来构建二叉树,这里的构造是在区间范围内找到最大值 1.返回值为TreeNode*,参数为nums和规定取值范围的左右标志 2.如果left>right,说明此时递归结束…

tiechui_lesson05_内核小文件拷贝

主要学习在内核中的文件操作,包括文件的打开,创建,读取,写入,查询文件属性等。 涉及的API和宏函数 ZwOpenFileZwCreateFileZwQueryInformationFileZwReadFileZwWriteFileZwCloseInitializeObjectAttributes 1.文件的…

springboot整合jave2实现音频格式转换

java中处理音频的常用框架 首先了解FFmpeg FFmpeg是一款开源软件,用于生成处理多媒体数据的各类库和程序。FFmpeg可以转码、处理视频和图片(调整视频、图片大小,去噪等)、打包、传输及播放视频。作为最受欢迎的视频和图像处理软…

vector、deque、list相关知识点

vector erase返回迭代器指向删除元素后的元素insert返回迭代器指插入的元素reserve只给容器底层开指定大小内存空间,并不添加新元素 deque 底层数据结构 动态开辟的二维数组,一维数组从2开始,以2倍方式扩容,每次扩容和&#x…

Windows服务搭建web网站,使用cpolar内网穿透实现公网访问

文章目录 概述1. 搭建一个静态Web站点2. 本地浏览测试站点是否正常3. 本地站点发布公网可访问3.1 安装cpolar内网穿透3.2 创建隧道映射公网地址3.3 获取公网URL地址 4. 公网远程访问内网web站点5. 配置固定二级子域名5.1 保留二级子域名5.2 配置二级子域名 6. 测试访问二级子域…

一篇文章带您区分GNSS欺骗模拟测试的两种方式

写在前面 注意:提供的设备与案例、使用指南等指导性文件是为了在测试环境中对接收机的抗干扰能力进行验证,而非出于欺骗或干扰真实环境中的GNSS信号的目的!请确保通过线缆连接应用或暗室应用,若因为违规使用产生的任何法律后果和…

1703_LibreOffice常用功能使用体验

全部学习汇总: GreyZhang/windows_skills: some skills when using windows system. (github.com) 首先需要说明的是我不是一个重度Office用户,甚至算不上一个重度的Office用户。我使用的Office软件最多的功能就是文档编辑,绝大多数时候还是文…