当前位置: 首页 > news >正文

【小梦C嘎嘎——启航篇】内存管理小知识~

【小梦C嘎嘎——启航篇】内存管理小知识~😎

  • 前言🙌
    • malloc/calloc/realloc的区别?
    • new 与 delete
      • new与delete要找好搭档才能保证万无一失
    • new 与 delete的内部实现细节是怎么样的呢???
        • new 的内部实现细节
        • delete的内部实现细节
      • 经典问题:malloc/free 与new/delete 的区别是什么???
      • 抛异常的基本使用
    • 小知识点:cout 流插入 不能打印出char*指针的地址
  • 总结撒花💞

追梦之旅,你我同行

   
😎博客昵称:博客小梦
😊最喜欢的座右铭:全神贯注的上吧!!!
😊作者简介:一名热爱C/C++,算法等技术、喜爱运动、热爱K歌、敢于追梦的小博主!

😘博主小留言:哈喽!😄各位CSDN的uu们,我是你的博客好友小梦,希望我的文章可以给您带来一定的帮助,话不多说,文章推上!欢迎大家在评论区唠嗑指正,觉得好的话别忘了一键三连哦!😘
在这里插入图片描述

前言🙌

    哈喽各位友友们😊,我今天又学到了很多有趣的知识现在迫不及待的想和大家分享一下! 都是精华内容,可不要错过哟!!!😍😍😍

malloc/calloc/realloc的区别?

这是一个经典的问题,有时面试也会这么问你。我的理解是:malloc可以向堆区动态申请一段连续的空间,realloc 的话主要是完成扩容操作,其扩容又可以分为两种方式:1.原地扩容 ;2.异地扩容。异地扩容的代价比较高,因为它要在堆区去找一块能够满足需求的空间,然后将原来的数据内容拷贝到新申请的空间里面,然后再把原来申请的空间释放掉。而calloc的话就是在malloc的基础上,能够将自己申请的空间进行初始化操作。以上就是他们三者的区别与联系啦~

new 与 delete

在C语言中我们知道有malloc ,realloc,calloc 这些可以在堆区中申请资源,可以用free释放掉堆上开辟的空间。那为什么C++还自己搞一套呢???不要问,C嘎嘎祖师爷那么设计一定有他的道理!!!接下来,我就来分析一下为什么。

new与delete要找好搭档才能保证万无一失

由于我们场景需求的多样,因此new与delete产生了不同的搭档方式以满足我们的需求。简单概括为:

  • 一个变量空间的申请与释放:new 变量类型(val) <-----> delete 变量名
  • 一个变量空间的申请与释放:new 变量类型【变量个数】(val) <-----> delete【】 变量名
#include<iostream>
using namespace std;class A
{
public:A(int a = 0):_a(a){cout << "A(int a = 0)" << endl;}~A(){cout << "~A()" << endl;}
private:int _a;
};int main()
{int* a = new int(10);cout << *a << endl;delete a;A* ptr1 = new A[10];delete[] ptr1;return 0;
}

在这里插入图片描述

new与delete要找好搭档才能保证万无一失,如果随意搭档可能会出错的。例如下面这个场景就会导致运行错误。


class A
{
public:A(int a = 0):_a(a){cout << "A(int a = 0)" << endl;}~A(){cout << "~A()" << endl;}
private:int _a;
};int main()
{int* a = new int(10);cout << *a << endl;A* ptr1 = new A[10];delete ptr1;//delete[] ptr1;return 0;
}

在这里插入图片描述

因此,我们在使用的时候,一定要根据场景的需求去选择new 与 delete 的 匹配搭档。

new 与 delete的内部实现细节是怎么样的呢???

new 的内部实现细节

其实new 之所以可以申请空间并且完成初始化操作,其实其内部是调用了 malloc 和 构造函数来实现的。那它们又是怎么调用malloc和构造的呢?内部实现的细节是怎么样的? 其实这里使用了封装的方法,其内部实现是写了一个operator new函数,这个函数里面封装了malloc函数的调用以及抛异常的实现。因此,operator new函数就完成了new的开空间和如果new失败了会抛异常的功能。然后调用new,编译器会自动调用构造函数进行对象的初始化操作。

delete的内部实现细节

其实delete之所以可以释放空间并且完成对象资源清理的工作,其实其内部是调用了free函数 和 析构函数来实现的。那它们又是怎么调用free函数 和 析构函数的呢?内部实现的细节是怎么样的? 其实这里也使用了封装的方法,其内部实现是写了一个operator delete函数,这个函数里面封装了free函数的调用。因此,operator delete函数就完成了对象资源的释放。然后调用delete,编译器会自动调用析构函数进行对象空间的释放。

从他们内部实现的细节可以看出,如果只是对内置类型变量,那么使用malloc + free 与使用 new + delete 都可以完成空间的开辟和释放。但是,对于自定义类型就只能用new+delete。最主要的原因就是:new和delete会自动调用构造函数和析构函数,而malloc和free不能。

经典问题:malloc/free 与new/delete 的区别是什么???

我的理解是:

  • 从语法角度上看:

    malloc ,free是函数,而new与delete是操作符。malloc需要自己手动计算所要申请空间的大小而new直接加类型然后在后面【】里面写上对象个数即可。malloc 返回的是vold*指针需要强转,而new不用,返回的就是该对象类型的指针。malloc开辟失败是会返回NULL,我们需要自己写一个检查代码来判断是否开辟失败,而new开辟失败会抛出异常,无需我们写检查代码。malloc只能完成申请空间的功能,而new既可以申请空间又可以进行初始化。

  • 从底层原理实现的角度上看:

    申请自定义类型对象时,malloc/free只会开辟空间,不会调用构造函数与析构函数,而new
    在申请空间后会调用构造函数完成对象的初始化,delete在释放空间前会调用析构函数完成
    空间中资源的清理

抛异常的基本使用

C++中的new有抛异常的功能。而try()catch()则可以去捕获new抛出的异常。

首先需要将要检查的代码放在try()里面,或者在这里面进行调用,才能够对该代码段进行异常的检查和捕获。一旦捕获到异常,就会自动跳转到catch()里面,然后进行异常的处理。下面是一个在32位平台上的应用举例:

void func()
{char* p1 = new char[0x7fffffff];cout << (void*)p1 << endl;cout << "hello world" << endl;
}int main()
{try{func();}catch (const exception& e){cout << e.what() << endl;}return 0;
}

运行结果截图

在这里插入图片描述

小知识点:cout 流插入 不能打印出char*指针的地址

原因:cout 会自动识别其为字符串,并按照字符串的格式进行打印,遇到"/0"就会结束打印。

解决方案:将其强转为其他类型即可解决。

错误代码:

在这里插入图片描述

程序运行结果:

在这里插入图片描述

修改后的代码:

在这里插入图片描述

运行结果:

在这里插入图片描述

总结撒花💞

   希望大家通过阅读此文有所收获
   😘如果我写的有什么不好之处,请在文章下方给出你宝贵的意见😊。如果觉得我写的好的话请点个赞赞和关注哦~😘😘😘

相关文章:

【小梦C嘎嘎——启航篇】内存管理小知识~

【小梦C嘎嘎——启航篇】内存管理小知识~&#x1f60e; 前言&#x1f64c;malloc/calloc/realloc的区别&#xff1f;new 与 deletenew与delete要找好搭档才能保证万无一失 new 与 delete的内部实现细节是怎么样的呢&#xff1f;&#xff1f;&#xff1f;new 的内部实现细节dele…...

ClickHouse查看执行计划(EXPLAIN语法)

1.EXPLAIN 语法示例 EXPLAIN [AST | SYNTAX | QUERY TREE | PLAN | PIPELINE | ESTIMATE | TABLE OVERRIDE] [setting value, ...] [ SELECT ... | tableFunction(...) [COLUMNS (...)] [ORDER BY ...] [PARTITION BY ...] [PRIMARY KEY] [SAMPLE BY ...] [T…...

线程池

线程池 什么是线程池&#xff1f; 想象一下 假设我是个漂亮妹子&#xff0c;这时候接受了舔狗A的表白&#xff0c;随着时间的推移&#xff0c;逐渐不喜欢A这小子了&#xff0c;于是我就想换个男朋友&#xff0c;可是 1.处理分手&#xff0c;需要消耗一定成本 2.再找一个新对象…...

配置:Terminal和oh-my-posh

目录 命令行安装oh-my-posh查看安装情况配置PowerShell启用oh-my-posh、设置主题配色安装字体Terminal中的配置 命令行安装oh-my-posh Set-ExecutionPolicy Bypass -Scope Process -Force; Invoke-Expression ((New-Object System.Net.WebClient).DownloadString(https://ohmy…...

数据结构--BFS求最短路

数据结构–BFS求最短路 BFS求⽆权图的单源最短路径 注&#xff1a;⽆权图可以视为⼀种特殊的带权图&#xff0c;只是每条边的权值都为1 以 2 为 b e g i n 位置 以2为begin位置 以2为begin位置 代码实现 //求顶点u到其他顶点的最短路径 void BFS_MIN_Distance(Graph G, int u…...

FPGA应用学习笔记----定点除法的gold算法流水线设计

猜一个Y0 a和b上下都Y0 分母越接近一&#xff0c;分子就越接近答案 误差&#xff1a; 下一步迭代为 Y的迭代值&#xff1a; 误差值&#xff1a; 代码的实现如上所示...

Nginx转发的原理和负载均衡

一、Nginx转发的原理 Nginx是一个高性能的反向代理服务器&#xff0c;它可以用于实现请求的转发和负载均衡。以下是Nginx转发的基本原理&#xff1a; 客户端发送请求&#xff1a;客户端向Nginx服务器发送HTTP请求。 Nginx接收请求&#xff1a;Nginx服务器接收到客户端的请求。…...

怎么换ip地址 电脑切换ip地址方法

互联网时代&#xff0c;IP地址是我们在网络上进行通信和访问的身份标识。有时候&#xff0c;我们可能需要更改IP地址&#xff0c;以便获得更好的网络体验或绕过某些限制。本文将介绍如何使用深度IP转换器来更改IP地址。 1&#xff1a;了解IP地址 IP地址是一个由数字和点组成的标…...

软件设计基础

巩固基础&#xff0c;砥砺前行 。 只有不断重复&#xff0c;才能做到超越自己。 能坚持把简单的事情做到极致&#xff0c;也是不容易的。 软件项目管理。 在经历了软件危机和大连的软件项目失败以后&#xff0c;人们对软件工程专业的现状进行了多次分析。得出了普遍性的结论&…...

OptaPlanner笔记5

2.4 与spring boot集成 2.4.4 添加依赖 <dependency><groupId>org.optaplanner</groupId><artifactId>optaplanner-spring-boot-starter</artifactId> </dependency>2.4.8 创建求解器服务 import org.optaplanner.core.api.solver.Solv…...

PS注意事项优漫动游

PS入门注意事项AdobePhotoshop是目前最流行的平面设计软件之一。可以说&#xff0c;只要你接触平面设计&#xff0c;那么无论早晚&#xff0c;你都要和它打交道。关于Photoshop&#xff0c;要说的实在太多太多&#xff0c;但不论你想让它成为你的左膀右臂&#xff0c;或者仅仅是…...

matplotlib 判断鼠标是否点击在当前线上

在开发中有一个需求&#xff1a;对生成的一条线进行拖拽。 我将这个方法实现在线所在的类里&#xff0c;这个过程中需要判断鼠标是否点击在当前线上&#xff0c;从而实现拖拽。 实现代码如下&#xff1a; # 点击事件 def on_press(self,event):if event.inaxes ! self.ax:retur…...

bash中(冒号破折号)的用法 —— 筑梦之路

${PUBLIC_INTERFACE:-eth0} :- 的用途是什么&#xff1f; 含义&#xff1a;如果 $PUBLIC_INTERFACE 存在且不是 null&#xff0c;则返回其值&#xff0c;否则返回 "eth0"。 ${parameter:-word} 使用默认值。如果 parameter 未设置或为 null&#xff0c;则 word 的扩…...

LeetCode150道面试经典题--同构字符串(简单)

1.题目 给定两个字符串 s 和 t &#xff0c;判断它们是否是同构的。如果 s 中的字符可以按某种映射关系替换得到 t &#xff0c;那么这两个字符串是同构的。每个出现的字符都应当映射到另一个字符&#xff0c;同时不改变字符的顺序。不同字符不能映射到同一个字符上&#xff0c…...

Redis - 数据类型映射底层结构

简介 从数据类型上体现就是&#xff0c;同一个数据类型&#xff0c;在不同的情况下会使用不同的编码类型&#xff0c;底层所使用的的数据结构也不相同。 字符串对象 字符串对象的编码可以是 int、raw 和 embstr 三者之一。 embstr 编码是专门用于保存简短字符串的一种优化编…...

MySQL数据库表的增删查改 - 进阶

一&#xff0c;数据库约束 1.1 约束对象 not null - 该列不能为空unique - 保证该列的每一行都不一样default - 规定没有给列赋值时的默认值&#xff08;自定义&#xff09;primary key - not null 和 unique 的结合&#xff0c;会给该列添加一个索引&#xff0…...

8086汇编语言工作环境 百度网盘下载

链接&#xff1a;https://pan.baidu.com/s/1-1K7gX859xejaUK70OTgtw?pwdbfa5 提取码&#xff1a;bfa5 为了方便下载&#xff0c;找了很多资料&#xff0c;也是从其他人那边分享过来的&#xff0c;也方便其他人 文件内容&#xff1a;...

ES6 解构

解构的语法 … {} 解构的语法中&#xff0c;...&#xff08;展开运算符&#xff09;和 {}&#xff08;对象字面量&#xff09;扮演着不同的角色。 ...&#xff08;展开运算符&#xff09;&#xff1a; 在解构中&#xff0c;... 被用作展开运算符&#xff0c;用于将数组或对象中…...

React三个状态时触发的相应钩子

01.初始化状态。 这个阶段由render&#xff08;&#xff09;函数触发&#xff1b; 1.constructor(); 2.componentWillMount(); 在17版本以后改为UNSAFE_componentWillMount() reason&#xff1a;react为组件异步渲染做准备&#xff1b; 3.render(); 4.componentDidMount(); 这…...

阿里云服务器部署Drupal网站教程基于CentOS系统

阿里云百科分享如何在CentOS 7操作系统的ECS实例上搭建Drupal电子商务网站。Drupal是使用PHP语言编写的开源内容管理框架&#xff08;CMF&#xff09;&#xff0c;它由内容管理系统&#xff08;CMS&#xff09;和PHP开发框架&#xff08;Framework&#xff09;共同构成。它用于…...

synchronized 学习

学习源&#xff1a; https://www.bilibili.com/video/BV1aJ411V763?spm_id_from333.788.videopod.episodes&vd_source32e1c41a9370911ab06d12fbc36c4ebc 1.应用场景 不超卖&#xff0c;也要考虑性能问题&#xff08;场景&#xff09; 2.常见面试问题&#xff1a; sync出…...

【OSG学习笔记】Day 18: 碰撞检测与物理交互

物理引擎&#xff08;Physics Engine&#xff09; 物理引擎 是一种通过计算机模拟物理规律&#xff08;如力学、碰撞、重力、流体动力学等&#xff09;的软件工具或库。 它的核心目标是在虚拟环境中逼真地模拟物体的运动和交互&#xff0c;广泛应用于 游戏开发、动画制作、虚…...

通过Wrangler CLI在worker中创建数据库和表

官方使用文档&#xff1a;Getting started Cloudflare D1 docs 创建数据库 在命令行中执行完成之后&#xff0c;会在本地和远程创建数据库&#xff1a; npx wranglerlatest d1 create prod-d1-tutorial 在cf中就可以看到数据库&#xff1a; 现在&#xff0c;您的Cloudfla…...

家政维修平台实战20:权限设计

目录 1 获取工人信息2 搭建工人入口3 权限判断总结 目前我们已经搭建好了基础的用户体系&#xff0c;主要是分成几个表&#xff0c;用户表我们是记录用户的基础信息&#xff0c;包括手机、昵称、头像。而工人和员工各有各的表。那么就有一个问题&#xff0c;不同的角色&#xf…...

(二)原型模式

原型的功能是将一个已经存在的对象作为源目标,其余对象都是通过这个源目标创建。发挥复制的作用就是原型模式的核心思想。 一、源型模式的定义 原型模式是指第二次创建对象可以通过复制已经存在的原型对象来实现,忽略对象创建过程中的其它细节。 📌 核心特点: 避免重复初…...

Keil 中设置 STM32 Flash 和 RAM 地址详解

文章目录 Keil 中设置 STM32 Flash 和 RAM 地址详解一、Flash 和 RAM 配置界面(Target 选项卡)1. IROM1(用于配置 Flash)2. IRAM1(用于配置 RAM)二、链接器设置界面(Linker 选项卡)1. 勾选“Use Memory Layout from Target Dialog”2. 查看链接器参数(如果没有勾选上面…...

NFT模式:数字资产确权与链游经济系统构建

NFT模式&#xff1a;数字资产确权与链游经济系统构建 ——从技术架构到可持续生态的范式革命 一、确权技术革新&#xff1a;构建可信数字资产基石 1. 区块链底层架构的进化 跨链互操作协议&#xff1a;基于LayerZero协议实现以太坊、Solana等公链资产互通&#xff0c;通过零知…...

基于matlab策略迭代和值迭代法的动态规划

经典的基于策略迭代和值迭代法的动态规划matlab代码&#xff0c;实现机器人的最优运输 Dynamic-Programming-master/Environment.pdf , 104724 Dynamic-Programming-master/README.md , 506 Dynamic-Programming-master/generalizedPolicyIteration.m , 1970 Dynamic-Programm…...

关键领域软件测试的突围之路:如何破解安全与效率的平衡难题

在数字化浪潮席卷全球的今天&#xff0c;软件系统已成为国家关键领域的核心战斗力。不同于普通商业软件&#xff0c;这些承载着国家安全使命的软件系统面临着前所未有的质量挑战——如何在确保绝对安全的前提下&#xff0c;实现高效测试与快速迭代&#xff1f;这一命题正考验着…...

MySQL JOIN 表过多的优化思路

当 MySQL 查询涉及大量表 JOIN 时&#xff0c;性能会显著下降。以下是优化思路和简易实现方法&#xff1a; 一、核心优化思路 减少 JOIN 数量 数据冗余&#xff1a;添加必要的冗余字段&#xff08;如订单表直接存储用户名&#xff09;合并表&#xff1a;将频繁关联的小表合并成…...