C++学习————第八天(C/C++内存管理)

目录

1、1.C/C++内存分布

2、 C语言中动态内存管理方式:malloc/calloc/realloc/free

3、C++内存管理方式

3.1 new/delete操作内置类型

3.2 new和delete操作自定义类型

4.operator new与operator delete函数

5. new和delete的实现原理

5.1 内置类型   

5.2 自定义类型

>)delete注意事项

1、1.C/C++内存分布

我们先来看下面的一段代码和相关问题

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. 选择题:选项: A.栈 B.堆 C.数据段(静态区) D.代码段(常量区)globalVar在哪里?__C__  staticGlobalVar在哪里?__C__staticVar在哪里?__C__  localVar在哪里?__A__num1 在哪里?__A__分析:globalVar全局变量在数据段 staticGlobalVar静态全局变量在静态区staticVar静态局部变量在静态区  localVar局部变量在栈区num1局部变量在栈区char2在哪里?__A__  *char2在哪里?__A__pChar3在哪里?__A__   *pChar3在哪里?__D__ptr1在哪里?__A__    *ptr1在哪里?__B__分析:char2局部变量在栈区  char2是一个数组,把后面常量串拷贝过来到数组中,数组在栈上,所以*char2在栈上pChar3局部变量在栈区   *pChar3得到的是字符串常量字符在代码段ptr1局部变量在栈区     *ptr1得到的是动态申请空间的数据

【说明】

1、栈又叫堆栈–非静态局部变量/函数参数/返回值等等,栈是向下增长的,栈可以通过函数_alloca进行动态分配,不过注意,所分配空间不能通过free或delete进行释放,频繁的申请空间和释放空间,容易造成内存碎片,甚至内存泄漏,栈区由于是自动管理,不存在此问题

2、内存映射段是高效的I/O映射方式,用于装载一个共享的动态内存库。用户可使用系统接口创建共享共享内存,做进程间通信。(现在只需要了解, 后面在linux中会提到)
3、堆用于程序运行时动态内存分配,堆是可以上增长的。堆无法静态分配,只能动态分配
4、数据段–存储全局数据和静态数据。
5、代码段–可执行的代码/只读常量。


2、 C语言中动态内存管理方式:malloc/calloc/realloc/free


void Test()
{int* p1 = (int*)malloc(sizeof(int));free(p1);// 1.malloc/calloc/realloc的区别是什么?int* p2 = (int*)calloc(4, sizeof(int));int* p3 = (int*)realloc(p2, sizeof(int) * 10);// 这里需要free(p2)吗?free(p3);
}

1. malloc/calloc/realloc的区别?

三者都是分配内存,都是stdlib.h库里的函数,但是也存在一些差异。

(1)malloc函数。其原型void *malloc(unsigned int num_bytes);
              num_byte为要申请的空间大小,需要我们手动的去计算,如int *p = (int*)

malloc( 20*sizeof(int)),如果编译器默认int为4字节存储的话,那么计算结果是80Byte,一次申请一个80Byte的连续空间,并将空间基地址强制转换为int类型,赋值给指针p,此时申请的内存值是不确定的。

(2)calloc函数,其原型void *calloc(size_t n, size_t size);
        其比malloc函数多一个参数,并不需要人为的计算空间的大小,比如如果他要申请20个int类型空间,会int *p = (int *)calloc(20, sizeof(int)),这样就省去了人为空间计算的麻烦。但这并不是他们之间最重要的区别,malloc申请后空间的值是随机的,并没有进行初始化,而calloc却在申请后,对空间逐一进行初始化,并设置值为0;

既然calloc不需要计算空间并且可以直接初始化内存避免错误,那为什么不直接使用calloc函数,那要malloc要什么用呢?
实际上,任何事物都有两面性,有好的一面,必然存在不好的地方。这就是效率。calloc函数由于给每一个空间都要初始化值,那必然效率较malloc要低,并且现实世界,很多情况的空间申请是不需要初始值的,这也就是为什么许多初学者更多的接触malloc函数的原因。

(3)realloc函数和上面两个有本质的区别,其原型void realloc(void *ptr, size_t new_Size)
用于对动态内存进行扩容(及已申请的动态空间不够使用,需要进行空间扩容操作,ptr为指向原来空间基址的指针, new_size为接下来需要扩充容量的大小。


3、C++内存管理方式

       C语言内存管理方式在C++中可以继续使用,但有些地方就无能为力,而且使用起来比较麻烦,因此C++又提出了自己的内存管理方式:通过new和delete操作符进行动态内存管理。

3.1 new/delete操作内置类型

void Test()
{//内置类型// 管理对象// 动态申请一个int类型的空间int* ptr4 = new int;// 动态申请一个int类型的空间并初始化为10int* ptr5 = new int(10);//管理对象数组// 动态申请10个int类型的空间int* ptr6 = new int[3];//动态申请10个int类型的空间,并初始化为1 2 3 4int* ptr7 = new int[10] {1, 2, 3, 4}; //后面的会默认初始化为0//释放一个对象delete ptr4; delete ptr5;//释放多个对象delete[] ptr6; delete[] ptr7;
}

注意:申请和释放单个元素的空间,使用new和delete操作符,申请和释放连续的空间,使用new[]和delete[],注意:匹配起来使用。

3.2 new和delete操作自定义类型

       new/delete 和 malloc/free最大区别是 new/delete对于【自定义类型】除了开空间还会调用构造函数和析构函数

class A
{
public:A(int a = 0): _a(a){//cout << "A():" << this << endl;cout << "A():" << endl;}A(int a1, int a2){cout << "A(int a1, int a2)" << endl;}A(const A& aa): _a(aa._a){cout << "A(const A& aa)" << endl;}A& operator=(const A& aa){cout << "A& operator=(const A& aa)" << endl;if (this != &aa){_a = aa._a;}return *this;}~A(){//cout << "~A()" << this << endl;cout << "~A()" << endl;}
private:int _a;
};int main()
{// new/delete 和 malloc/free最大区别是// new/delete对于【自定义类型】除了开空间,还会调用构造函数和析构函数A* p1 = (A*)malloc(sizeof(A));A* p2 = new A(2);free(p1);delete p2;// 内置类型是几乎是一样的int* p3 = (int*)malloc(sizeof(int)); // Cint* p4 = new int;free(p3);delete p4;A* p5 = (A*)malloc(sizeof(A) * 10);A* p6 = new A[10]; //调用10次构造函数free(p5);delete[] p6; //调用10次析造函数//多个对象A aa1(1);A aa2(2);A aa3(3);A* p7 = new A[10]{ aa1,aa2,aa3 };delete[]p7;// 多参数A* p7 = new A[10]{ 1,2,3,4,5,{6,7}};//用1生成临时对象,然后被编译器合二为一(隐式对象转换)delete[]p7;return 0;
}

注意:在申请自定义类型的空间时,new会调用构造函数,delete会调用析构函数,而malloc与free不会

4.operator new与operator delete函数

1.new和delete是用户进行动态内存申请和释放的操作符,operator new 和operator delete是系统提供的全局函数
2.new在底层调用operator new全局函数来申请空间,delete在底层通过operator delete全局 函数来释放空间。

5. new和delete的实现原理

5.1 内置类型   

  如果申请的是内置类型的空间,new和malloc,delete和free基本类似,不同的地方是:
new/delete申请和释放的是单个元素的空间,new[]和delete[]申请的是连续空间,而且new在申请空间失败时会抛异常,malloc会返回NULL。

5.2 自定义类型

new的原理
1. 调用operator new函数申请空间
2. 在申请的空间上执行构造函数,完成对象的构造
delete的原理
1. 在空间上执行析构函数,完成对象中资源的清理工作
2. 调用operator delete函数释放对象的空间
new T[N]的原理
1. 调用operator new[]函数,在operator new[]中实际调用operator new函数完成N个对
象空间的申请
2. 在申请的空间上执行N次构造函数
delete[]的原理
1. 在释放的对象空间上执行N次析构函数,完成N个对象中资源的清理
2. 调用operator delete[]释放空间,实际在operator delete[]中调用operator delete来释
放空间

总结:new == operator new -> (malloc) + 构造函数
           ~~~~~~~~~~          delete == 析构函数 + operator delete -> (free)
           ~~~~~~~~~~          特别的:new失败了,抛异常, 不需要再检查返回值

>)delete注意事项

ClassA *pclassa=new ClassA[5];
delete pclassa;

析构函数此时只会调用1次,要想完整释放数组空间,需要使用[]
注意:程序可能崩溃

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/1619.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【QT学习】8.qt事件处理机制,事件过滤器,自定义事件

1.qt事件处理机制 事件处理&#xff1a; 当用户移动鼠标的时候 &#xff0c;创建一个 鼠标移动事件对象 然后把这个对象放到 事件队列里面去&#xff0c;事件管理器 从队列中 取出事件&#xff0c;然后 调用其对应的事件处理函数。 多态机制&#xff1a; &#x…

【xhs爬虫软件】把小红书评论comment接口封装成GUI采集工具!

用Python开发爬虫采集软件&#xff0c;可自动抓取小红书评论数据&#xff0c;并且含二级评论。 小红书的评论接口URL是&#xff1a; https://edith.xiaohongshu.com/api/sns/web/v2/comment/page 开发者模式分析过程&#xff1a; 进而封装成GUI界面软件&#xff0c;如下&…

17.基础乐理-调式、自然大调式(C大调、D大调。。。)

调式&#xff1a; 若干个音&#xff0c;按照某种规则排列起来&#xff0c;就是调式&#xff0c;调式是一个非常大&#xff0c;非常抽象的概念&#xff0c;调式这两个字是一个统称&#xff0c;当明确了 若干个音 到底有几个音&#xff0c;某种规则到底是什么规则之后&#xff0c…

【精】Devops实战学习CI/CD落地方案#CI篇#

目录 先有个大概了解 基本概念 CI/CD Devops 阿里云效 devops产品 K8s jenkins docker git maven 知行合一&#xff0c;上手操作 实操记录 安装VMware 安装并配置虚拟机 安装并配置docker docker安装 修改镜像源&#xff08;关键且易出错&#xff09; CentOS…

Spring Security 入门篇(一)-- 简介

引言 Spring Security 官方文档 https://spring.io/projects/spring-security Spring Security 中文文档 &#xff1a; https://springdoc.cn/spring-security/ Spring Cloud 中文文档 https://www.springcloud.cc/spring-security.html#overall-architecture 一、简介 1. 什…

poll实现echo服务器的并发

poll实现echo服务器的并发 代码实现 #include <stdio.h> #include <string.h> #include <sys/types.h> #include <sys/socket.h> #include <stdlib.h> #include <arpa/inet.h> #include <sys/time.h> #include <unistd.h> #…

【JAVA】实现只有一个窗口弹出的底层逻辑——单身模式

目录 背景说明 代码实现 手写笔记 背景说明 有的时候&#xff0c;当你点击一个选项时会弹出来多个窗口&#xff0c;而有的时候只会弹出一个。 实际上&#xff0c;弹出多个窗口就是创建了多个相同的对象&#xff0c;而只弹出一个就是我们今天即将分享的单身模式——一个类只产生…

【Python】使用Python计算简单数值积分

题外话&#xff0c;Python语言命名的来源&#xff1a;&#xff08;见下图&#xff09;Monty Python巨蟒剧团 1、积分题目&#xff08;3&#xff09; 2、解析解答 3、Python计算代码 import math import scipy.integrate as integrate# 积分区间 # x_min 0.0 # 1 # x_min …

润石科技(RUNIC)汽车电子应用方案和物料选型

一、润石科技&#xff08;RUNIC&#xff09;简介 江苏润石科技有限公司是一家专注于高性能、高品质模拟/混合信号集成电路研发和销售的高科技半导体设计公司。公司主要产品线分为两类&#xff1a;信号链和电源管理&#xff0c;其中信号链包含运算放大器、比较器、模拟开关、数…

王者荣耀防御塔如何开发!新手小白做游戏开发采坑经过。phaser前端游戏框架

好嘞&#xff0c;游戏开发框架是js 开发的网页小游戏&#xff01; phaser这个框架。好我们先上图&#xff01; 目前大概是这么一个样子。 然后防御塔功能呢。简单的说就是当人物进去的时候打他。人物扣血。 我们的小人物是这样的代码 遇到的问题如下&#xff1b; 小白刚开始…

C++从入门到精通——模板

模板 前言一、泛型编程二、函数模板函数模板的概念函数模板格式示例 函数模板的原理函数模板的实例化隐式实例化显式实例化示例 auto做模板函数的返回值模板参数的匹配原则总结 三、类模板类模板的定义格式类模板的实例化 前言 C模板是C语言中的一种泛型编程技术&#xff0c;可…

服务器渲染技术(JSPELJSTL)

目录 前言 一.JSP 1.基本介绍 3.page指令(常用) 4.JSP三种常用脚本 4.1 声明脚本 <%! code %> 4.2 表达式脚本 <% code %> 4.3 代码脚本 <% code %> 4.4 注释 <%-- 注释 --%> 5. JSP 内置对象 5.1 基本介绍 5.2 九个内置对象 6.JSP域对象 二…

Ubuntu20.04 ISAAC SIM仿真下载使用流程

机器&#xff1a;华硕天选X2024 显卡&#xff1a;4060Ti ubuntu20.04 安装显卡驱动版本&#xff1a;525.85.05 参考&#xff1a; What Is Isaac Sim? — Omniverse IsaacSim latest documentationIsaac sim Cache 2023.2.3 did not work_isaac cache stopped-CSDN博客 Is…

linux 安装openjdk-1.8

安装命令 yum install java-1.8.0-openjdk-1.8.0.262.b10-1.el7.x86_64查看安装路径 find / -name java 默认的安装路径 /usr/lib/jvm 查看到jre 以及java-1.8.0-openjdk-1.8.0.262.b10-1.el7.x86_64 配置环境变量 vim /etc/profile 添加的内容 export JAVA_HOME/usr/li…

每日一题:地下城游戏

恶魔们抓住了公主并将她关在了地下城 dungeon 的 右下角 。地下城是由 m x n 个房间组成的二维网格。我们英勇的骑士最初被安置在 左上角 的房间里&#xff0c;他必须穿过地下城并通过对抗恶魔来拯救公主。 骑士的初始健康点数为一个正整数。如果他的健康点数在某一时刻降至 0…

基于非线性控制策略的电力电子电路——DC-DC电路的3种滑模控制器【MATLAB/simulink】

第一种&#xff0c;滞环滑模控制器Buck电路 在滑模控制系统中&#xff0c;采用滞环技术&#xff0c;直接将切换函数转换成开关控制信号&#xff0c;滞环技术被看做一种降低系统结构的切换频率的调制方法&#xff0c;业界也把基于滞环滑模技术实现的滑模控制称为直接滑模控制技…

分类网络总结

欢迎大家订阅我的专栏一起学习共同进步&#xff0c;主要针对25届应届毕业生 祝大家早日拿到offer&#xff01; lets go http://t.csdnimg.cn/dfcH3 目录 4. 经典分类网络与发展 4.1 AlexNet 4.2 VGGNet 4.3 GoogLeNet Inception 4.4 ResNet 4.5 DenseNet 4.6 MobileN…

Python基础04-操作系统中的文件与目录操作

在与操作系统交互时&#xff0c;我们经常需要执行文件和目录的操作。Python提供了丰富的库来帮助我们完成这些任务。以下是一些常见的操作&#xff0c;以及如何使用Python代码来实现它们。 1. 导航文件路径 在不同的操作系统中&#xff0c;文件路径的格式可能不同。Python的o…

提取出图像的感兴趣区域

这是我们的原图像 将图像的数值统计后进行条形图展示 import matplotlib.pyplot as plt from PIL import Image import numpy as np# 图像路径 image_path r"D:\My Data\Figure\OIP.jpg"# 打开图像 image Image.open(image_path)# 将图像转换为numpy数组 image_ar…

关于实验报告添加题注为0以及页面断层的解决办法

1.事情起源于最近在写实验报告和课设说明书时出现图的题注是图0-1等不遵循设置的章节标号&#xff0c;于是我在查询和个人尝试后发现必须设置多级编号并且自定义设置对应的样式为标题几 另外注意设置后必须题注也要设置对应的样式&#xff0c;否则还是0-1&#xff0c;不用编辑域…