13.C++内存管理2(C++ new和delete的使用和原理详解,内存泄漏问题)

⭐本篇重点:new, delete的使用和原理

⭐本篇代码:c++学习/04.c++-动态内存管理 · 橘子真甜/c++-learning-of-yzc - 码云 - 开源中国 (gitee.com)

目录

一. new和delete的使用

1.1 操作内置类型

1.2 操作自定义类型

二. new, delete与malloc, free的区别

2.1 相同点

2.2 不同点

三. new/delete原理(operator new 和 operator delete)

3.1 函数operator new / operator delete

3.2 new 和 delete 原理

四. 内存泄漏问题

4.1 什么是内存泄漏?内存泄漏的危害是什么?

4.2 内存泄漏的原因

4.3 避免内存泄漏

五. 下篇文章:STL简介


一. new和delete的使用

        new和delete是C++提供的一对操作符,可以完成对内存的管理。常用于完成内置类型和自定义类型的初始化

        其中,new用于开辟空间,delete使用释放空间

1.1 操作内置类型

#include <iostream>
using namespace std;int main()
{//1.new申请一个int型的变量,并将其赋值为999int* a = new int(999);//2.new申请10个int型的变量int* nums = new int[10];for (int i = 0; i < 10; i++){nums[i] = i;}cout << *a << endl;for (int i = 0; i < 10; i++){cout << nums[i] << " ";}//释放申请的空间delete a;delete[] nums;return 0;
}

分析:我们申请了并初始化一个变量a,以及一个数组nums。然后输出它们的值。运行结果如下:

要注意new和delete的搭配使用

new和delete用于开辟和释放一个元素。

new 类型[]  和 delete[] 用于开辟和释放连续的空间。

1.2 操作自定义类型

new和delete还能够操作自定义类型。

new初始化自定义类型的时候会调用其 构造函数

delete释放自定义类型的时候会调用其 析构函数

#include <iostream>
using namespace std;class A
{
public:A(int a = 0):_a(a){cout << "调用A的构造函数" << endl;}~A(){cout << "调用A的析构函数" << endl;}void print(){cout << _a << endl;}
private:int _a;
};
int main()
{A* p1 = new A;p1->print();A* p2 = new A(1);p2->print();A* p3 = new A[5]; //初始化连续的变量delete p1;delete p2;delete[] p3;return 0;
}

运行结果如下:

二. new, delete与malloc, free的区别

2.1 相同点

new/delete 与 malloc/free 都是在堆上开辟空间,并且需要用户手动释放空间

2.2 不同点

new/delete是C++提供的操作符,malloc/free是C语言提供的库函数

new/delete申请空间会对其进行初始化,malloc/free不会进行初始化

new/delete申请空间会调用其构造函数,释放空间会调用析构函数,malloc/free 申请释放空间不会调用构造函数和析构函数

举例:

#include <iostream>
using namespace std;class A
{
public:A(int a = 0):_a(a){cout << "调用A的构造函数" << endl;}~A(){cout << "调用A的析构函数" << endl;}void print(){cout << _a << endl;}
private:int _a;
};int main()
{//new/delete申请空间会初始化cout << "new/delete" << endl;A* p1 = new A;delete p1;//malloc/free申请空间不会初始化cout << "malloc/free" << endl;A* p2 = (A*)malloc(sizeof(A));if (NULL == p2){cout << "malloc error!" << endl;exit(1);}free(p2);p2 = NULL;return 0;
}

        malloc申请空间的时候,我们需要将返回的 void* 强制转化为我们需要的类型,并且需要计算我们需要申请的空间,还需要处理返回值为NULL的情况。

        new申请空间不需要强转,不许计算大小直接在后面放我们需要申请的空间类型即可,申请多个变量带上[]即可!不过使用new的时候需要捕获异常

三. new/delete原理(operator new 和 operator delete)

3.1 函数operator new / operator delete

        new/delete是用于动态申请和释放空间的操作符,而operator new 和 operator delete是系统提供的全局函数      

          new在底层调用operator new全局函数来申请空间,delete在底层通过 operator delete全局函数来释放空间。

 operator new 和 operator delete的部分源码如下

//operator new: 该函数通过malloc申请空间
void *__CRTDECL operator new(size_t size) _THROW1(_STD bad_alloc)
{
// try to allocate size bytes
void *p;
while ((p = malloc(size)) == 0)if (_callnewh(size) == 0){// report no memory// 如果申请内存失败了,这里会抛出bad_alloc 类型异常static const std::bad_alloc nomem;_RAISE(nomem);}
return (p);
}//operator delete: 该函数最终是通过free来释放空间的
void operator delete(void *pUserData)
{_CrtMemBlockHeader * pHead;RTCCALLBACK(_RTC_Free_hook, (pUserData, 0));if (pUserData == NULL)return;_mlock(_HEAP_LOCK);  /* block other threads */__TRY/* get a pointer to memory block header */pHead = pHdr(pUserData);/* verify block type */_ASSERTE(_BLOCK_TYPE_IS_VALID(pHead->nBlockUse));_free_dbg( pUserData, pHead->nBlockUse );__FINALLY_munlock(_HEAP_LOCK);  /* release other threads */__END_TRY_FINALLYreturn;
}//free的实现
#define   free(p)               _free_dbg(p, _NORMAL_BLOCK)

所以我们知道:operator new这个函数 是通过malloc来申请空间的。申请失败的时候会抛出异常,operator delete是通过free来实现释放空间的

3.2 new 和 delete 原理

对于内置类型,new/delete和malloc/free相似。区别见本篇2.2

对于自定义类型:

new原理:

        调用函数 operator new 申请空间,然后在申请的空间上调用构造函数完成对象的构造和初始化

delete原理:

        先在申请的空间上调用对象的析构函数进行清理,然后调用函数 operator free 进行释放对象的空间

四. 内存泄漏问题

4.1 什么是内存泄漏?内存泄漏的危害是什么?

        内存泄漏是因为程序员的疏忽和错误,没有去释放不再使用的内存空间。内存泄漏不是物理内存的消失,而是应用程序分配某段内存后,因为错误设计,导致程序失去了对这段内存的控制,造成空间浪费

        内存泄漏的危害:长期运行的程序出现内存泄漏会导致系统越来越卡,直到卡死。

4.2 内存泄漏的原因

        内存泄漏一般分为堆内存泄漏和系统资源泄漏。

堆:当我们使用malloc/new申请空间之后,使用完了却没有使用delete/new去释放这段空间。结果就是这段空间无法使用

系统资源泄露:指程序使用系统分配的资源,比方套接字、文件描述符、管道等没有使用对应的函数释放 掉,导致系统资源的浪费,严重可导致系统效能减少,系统执行不稳定。

4.3 避免内存泄漏

1 要有良好的工程设计和编码规范,申请完空间之后需要匹配释放空间。

2 有时候我们写了释放空间的代码,由于发生了异常导致这段代码没有被执行。这种时候就需要采用RAII思想和智能指针来解决

3 使用内存泄漏检测工具进行检测

五. 下篇文章:STL简介

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

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

相关文章

vue中动态渲染静态图片资源

不报错且f12查看元素的时候&#xff0c;显示的src说明已经渲染到html的src上&#xff0c;但是就是不显示在页面上 原因 在vue上&#xff0c;动态渲染静态图片资源&#xff08;比如从assets文件夹加载的图片&#xff09;需要注意打包工具对静态资源的解析方式 由于vue2的脚手…

uniapp 相关的swiper的一些注意事项

先推荐一个一个对标pc端swiper的uniapp版本 zebra-swiper 缺点是自定义分页器不是很好处理 不知道怎么弄 优点:可以进行高度自适应 &#xff08;这个uniapp原生swiper没有 只能动态修改 采用js 或者只有几种固定高度时采用变量修改&#xff09; <swiperref"lifeMiddle…

豆瓣书摘 | 爬虫 | Python

获取豆瓣书摘&#xff0c;存入MongoDB中。 import logging import timeimport requests from bs4 import BeautifulSoup from pymongo import MongoClientheaders {accept: text/html,application/xhtmlxml,application/xml;q0.9,image/avif,image/webp,image/apng,*/*;q0.8,…

(Linux)搭建静态网站——基于http/https协议的静态网站

简单了解nginx配置文件 1.下载并开启nginx服务 下载 [rootlocalhost ~]# dnf install nginx -y开启 [rootlocalhost ~]# systemctl restart nginx 1.(1)搭建静态网站——基于http协议的静态网站 实验1&#xff1a;搭建一个web服务器&#xff0c;访问该服务器时显示“hello w…

含有非期望产出的EBM模型及其改进模型

含有非期望产出的EBM模型及其改进模型 今天推出的是含有非期望产出的EBM模型及其两种改进模型。 **参考文献&#xff1a;《基于数字经济要素组合的绿色全要素生产率提升研究中的模型》**杜娟&#xff0c;张子承&#xff0c;王熠 本文构建了考虑非期望产出的改进EBM&#xff…

VScode学习前端-01

小问题合集&#xff1a; vscode按&#xff01;有时候没反应&#xff0c;有时候出来&#xff0c;是因为------>必须在英文状态下输入&#xff01; 把鼠标放在函数、变量等上面&#xff0c;会自动弹出提示&#xff0c;但挡住视线&#xff0c;有点不习惯。 打开file->pre…

使用 .NET 创建新的 WPF 应用

本教程介绍如何使用 Visual Studio 创建新的 Windows Presentation Foundation &#xff08;WPF&#xff09; 应用。 使用 Visual Studio&#xff0c;可以向窗口添加控件以设计应用的 UI&#xff0c;并处理这些控件中的输入事件以与用户交互。 在本教程结束时&#xff0c;你有一…

自存 sql常见语句和实际应用

关于连表 查询两个表 SELECT * FROM study_article JOIN study_article_review 查询的就是两个表相乘&#xff0c;结果为两个表的笛卡尔积 相这样 这种并不是我们想要的结果 通常会添加一些查询条件 SELECT * FROM study_articleJOIN study_article_review ON study_art…

嵌入式linux中QT信号与槽基本操作与实现

大家好,今天主要给大家分享一下,如何使用linux系统上的QT进行界面开发与实现。 第一:QT的信号与槽基本简介 在操作QT的时候,可以使用里面的信号与槽。所谓信号就是一个对象发出的信号,槽就是当这个对象发出这个信号时,对应连接的槽就发被执行或者触发。 进行信号与槽的连…

机器学习—学习曲线

学习曲线是帮助理解学习算法如何工作的一种方法&#xff0c;作为它所拥有的经验的函数。 绘制一个符合二阶模型的学习曲线&#xff0c;多项式或二次函数&#xff0c;画出交叉验证错误Jcv&#xff0c;以及Jtrain训练错误&#xff0c;所以在这个曲线中&#xff0c;横轴将是Mtrai…

【SpringBoot】什么是Maven,以及如何配置国内源实现自动获取jar包

前言 &#x1f31f;&#x1f31f;本期讲解关于Maven的了解和如何进行国内源的配置~~~ &#x1f308;感兴趣的小伙伴看一看小编主页&#xff1a;GGBondlctrl-CSDN博客 &#x1f525; 你的点赞就是小编不断更新的最大动力 &#x1f3…

基于xr-frame实现微信小程序的手部、手势识别3D模型叠加和石头剪刀布游戏功能

前言 xr-frame是一套小程序官方提供的XR/3D应用解决方案&#xff0c;基于混合方案实现&#xff0c;性能逼近原生、效果好、易用、强扩展、渐进式、遵循小程序开发标准。xr-frame在基础库v2.32.0开始基本稳定&#xff0c;发布为正式版&#xff0c;但仍有一些功能还在开发&#…

【Word】一键批量引用论文上标——将正文字体改为上标格式

【Word】一键批量引用论文上标——将正文字体改为上标格式 写在最前面Word一键批量引用论文上标技巧分享核心思路&#xff1a;Word 替换功能 通配符步骤详解1. 打开 Word 替换功能2. 输入通配符模式3. 设置替换格式为上标4. 批量替换 实际效果展示技巧扩展 &#x1f308;你好呀…

vue-next-admin框架配置(vue)

vue-next-admin 先安装依赖 npm i 依赖, npm run dev 运行 1.配置代理 2.把他的逻辑和自己的登录判断逻辑结合(我的放下面&#xff0c;可以参考哦&#xff0c;可以直接使用&#xff0c;到时候修改登录逻辑就好)&#xff0c;别忘了引入ajxio哦 const onSignIn async () &g…

CMake笔记:windows下构建一个简单项目

注&#xff1a;本人的临时记录&#xff0c;没什么参看价值&#xff0c;可移步https://cmake.org/cmake/help/v3.21/guide/tutorial/index.html 1. 概述 用CMake构建一个简单的项目&#xff0c;项目由一个exe以及一个dll组成&#xff0c;项目目录结构如上图&#xff0c;build_M…

Linux移植IMX6ULL记录 一:编译源码并支持能顺利进入linux

目录 前言 一、不修改文件进行编译 二、修改设备树文件进行编译 前言 我用的开发板是100_ask_imx6ull_pro&#xff0c;其自带的linux内核版本linux-4.9.88&#xff0c;然后从linux官网下载过来的linux-4.9.88版本的arch/arm/configs/defconfig和dts设备树文件并没有对imx6ull…

安卓手机root+magisk安装证书+抓取https请求

先讲一下有这篇文章的背景吧&#xff0c;在使用安卓手机fiddler抓包时&#xff0c;即使信任了证书&#xff0c;并且手机也安装了证书&#xff0c;但是还是无法捕获https请求的问题&#xff0c;最开始不知道原因&#xff0c;后来慢慢了解到现在有的app为了防止抓包&#xff0c;把…

linux 常用命令指南(存储分区、存储挂载、docker迁移)

前言&#xff1a;由于目前机器存储空间不够&#xff0c;所以‘斥巨资’加了一块2T的机械硬盘&#xff0c;下面是对linux扩容的一系列操作&#xff0c;包含了磁盘空间的创建、删除&#xff1b;存储挂载&#xff1b;docker迁移&#xff1b;anaconda3迁移等。 一、存储分区 1.1 …

学习虚幻C++开发日志——委托(持续更新中)

委托 官方文档&#xff1a;Delegates and Lamba Functions in Unreal Engine | 虚幻引擎 5.5 文档 | Epic Developer Community | Epic Developer Community 简单地说&#xff0c;委托就像是一个“函数指针”&#xff0c;但它更加安全和灵活。它允许程序在运行时动态地调用不…

Git入门图文教程 -- 深入浅出 ( 保姆级 )

01、认识一下Git&#xff01;—简介 Git是当前最先进、最主流的分布式版本控制系统&#xff0c;免费、开源&#xff01;核心能力就是版本控制。再具体一点&#xff0c;就是面向代码文件的版本控制&#xff0c;代码的任何修改历史都会被记录管理起来&#xff0c;意味着可以恢复…