【C++】动态内存管理new和delete
文章目录
- 一、C++的内存管理方式
- 二、new和delete的用法
- 1.操作内置类型
- 2.操作自定义内置类型
- 三、new和delete的底层实现
- 1.operator new和operator delete函数
- 2.new和delete的实现原理
- 四、定位new表达式
- 五、malloc/free和new/delete的区别
一、C++的内存管理方式
之前在C语言的动态内存管理我们学过,用来动态开辟空间的malloc/calloc/realloc和释放空间的free。C语言内存管理方式在C++中可以继续使用,但有些地方就无能为力,而且使用起来比较麻烦,因此C++将malloc和free封装起来并起了新的名字new和delete。
二、new和delete的用法
1.操作内置类型
new和delete是操作符,不是函数,不需要单独添加头文件。
动态申请一个int类型的空间
int* p1 = (int*)malloc(sizeof(int));
int* p2 = new int;
//释放内存
free(p1);
delete p2;
动态申请一个int类型的空间并初始化
int* p3 = (int*)malloc(sizeof(int));
*p3 = 1;
int* p4 = new int(1);
//释放内存
free(p3);
delete p4;
动态申请10个int类型的空间
int* p5 = (int*)malloc(sizeof(int) * 10);
int* p6 = new int[10];
//释放内存
free(p5);
delete[] p6;
动态申请10个int类型的空间并初始化(C++11)
int* p7 = (int*)malloc(sizeof(int) * 10);
int* p8 = new int[10]{ 1,2,3 };//后面未初始化的部分默认为0
//释放内存
free(p7);
delete[] p8;
注意:申请和释放单个元素的空间,使用new/delete操作符;申请和释放连续的空间,使用new[ ]和delete[ ],一定要配套使用!
通过对比,明显new和delete的使用更方便简洁;可以发现malloc与new的几个区别:
1.malloc和free是函数,而new和delete是操作符;
2.并且malloc申请空间时不会初始化,而new可以初始化,只需要在()(单个空间)或者{}(多个连续空间,C++11才引入)里赋值即可;
3.malloc申请空间时,需要手动计算空间大小并传递,new只需在其后跟上空间的类型即可,如果是多个对象,[ ]中指定对象个数。
4.malloc的返回值为void*,在使用时必须强转,new不需要,因为new后跟的是空间的类型
但是,这些优点并不足以解释C++不继续使用C语言的malloc和free,去创建一个新用法。new和delete最大的价值体现自定义类型的操作上。
2.操作自定义内置类型
对于内置类型,malloc/free与new/delete区别不大,真正的区别在于自定义类型。
malloc/free与new/delete最大的区别是:申请自定义类型对象时,malloc是纯粹的开辟空间,不会初始化;而new在申请空间后会调用构造函数完成对象的初始化,delete在释放空间前会调用析构函数完成空间中资源的清理。
对于需要资源申请的自定义类型更能体现其优势,以链表为例
new会先开辟空间再调用构造函数初始化,delete会先调用析构函数清理资源再释放空间,这点是与malloc/free的最大区别,也是C++新增用法的主要原因。
三、new和delete的底层实现
1.operator new和operator delete函数
new和delete是用户进行动态内存申请和释放的操作符,operator new 和operator delete是系统提供的全局函数,也是对malloc和free进行过封装的函数。
operator new和malloc的最大区别就是当申请错误时,处理的方式不一样。
malloc申请空间失败时会返回NULL
operator new函数实际通过malloc来申请空间,申请空间成功时直接返回,失败则抛异常
new和delete是对operator new和operator delete这两个全局函数进行的封装。所以new/delete与malloc/free的不同:malloc申请空间失败时,返回的是NULL,因此使用时必须判空,new不需要判空,申请失败会抛异常。
2.new和delete的实现原理
new在底层调用operator new全局函数来申请空间,delete在底层调用operator delete全局函数来释放空间。
通过反汇编可以看到,new先调用operator new(本质上是通过malloc)来申请空间,然后再调用构造函数进行初始化;delete先调用析构函数完成资源的清理,再调用operator delete释放空间。
对于内置类型
new和malloc,delete和free基本类似,不同的是:new/delete申请和释放的是单个元素的空间,new[]和delete[]申请的是连续空间,而且new在申请空间失败时会抛异常,malloc会返回NULL。
对于自定义类型
new原理:先调用operator new来申请空间,然后再调用构造函数进行初始化;
delete原理:先调用析构函数完成资源的清理,再调用operator delete释放空间。

四、定位new表达式
定位new表达式是在已分配的原始内存空间中调用构造函数初始化一个对象。
格式:
new(指针名)类型或者new(指针名)类型(参数值)
对于自定义类型的对象,需要使用new的定义表达式进行显示调用构造函数和析构函数进行初始化和资源清理。
class A
{
public:A(int a = 0): _a(a){cout << "A():" << this << endl;}~A(){cout << "~A():" << this << endl;}
private:int _a;
};
int main()
{// p1现在指向的只不过是与A对象相同大小的一段空间,还不能算是一个对象,因为构造函数没有执行A* pa = (A*)malloc(sizeof(A));new(pa)A;//显示调用构造函数//new(pa)A(10);pa->~A();//显示调用析构函数free(pa);return 0;
}
为什么要显示调用构造和析构?
因为pa是是指针类型,属于内置类型,不会自动调用构造和析构,所以需要显示调用。
定位new表达式在实际中一般是配合内存池使用。 内存池的工作原理是先向系统一次性申请比较大的空间,没有初始化,当我们每次去申请空间时就直接使用内存池里的空间,然后再进行初始化。
五、malloc/free和new/delete的区别
1.malloc和free是函数,new和delete是操作符;
2.malloc申请的空间不会初始化,new可以初始化;
3.malloc申请空间时,需要手动计算空间大小并传递,new只需在其后跟上空间的类型即可, 如果是多个对象,[ ]中指定对象个数即可;
4.malloc的返回值为void*, 在使用时必须强转,new不需要,因为new后跟的是空间的类型;
5.malloc申请空间失败时返回NULL,因此使用时必须判空,new不需要判空,申请失败会抛异常;
6.申请自定义类型对象时,malloc/free只会开辟空间,不会调用构造函数与析构函数,而new在申请空间后会调用构造函数完成对象的初始化,delete在释放空间前会调用析构函数完成空间中资源的清理。
相关文章:
【C++】动态内存管理new和delete
文章目录 一、C的内存管理方式二、new和delete的用法1.操作内置类型2.操作自定义内置类型 三、new和delete的底层实现1.operator new和operator delete函数2.new和delete的实现原理 四、定位new表达式五、malloc/free和new/delete的区别 一、C的内存管理方式 之前在C语言的动态…...
Java面向对象特性
Java继承: 继承的概念: 在Java中,继承(inheritance)是面向对象编程的一个重要概念,它允许一个类(子类)继承另一个类(父类)的属性和方法。通过继承,…...
odoo17 tree视图添加按钮
需求描述 点击下图中tree视图上的同步退货单按钮,弹出相应的form视图进行退货单同步,然后点击同步按钮调用后端python代码处理。 实现步骤 主要文件目录结构 js文件的创建 /** @odoo-module **/ import {registry } from "@web/core/registry"; import {listVie…...
PreparedStatement 与Statement 的区别,以及为什么推荐使用 PreparedStatement ?
在Java中,PreparedStatement和Statement都是用于执行SQL语句的重要接口,但它们在功能、安全性和性能上有着显著的差异。理解这些差异对于编写高效且安全的数据库应用程序至关重要。 Statement:基本的SQL执行者 首先,让我们从Sta…...
wsl ubuntu 安装Anaconda3步骤
如何在Ubuntu上安装Anaconda3呢?本章记录整个安装过程。 1、下载脚本 https://mirrors.bfsu.edu.cn/anaconda/archive/Anaconda3-2023.09-0-Linux-x86_64.sh 下载之后,将脚本上传到Ubuntu里。 2、安装脚本 bash Anaconda3-2021.11-Linux-x86_64.sh根据提示进行安装,提示输…...
Vue3响应式 ref全家桶
<template><div>{{ man.name }}<hr><button click"change">修改</button></div> </template> <script setup lang"ts"> const man {name:"cc"} const change () >{man.name "大cc&q…...
Mac(M1芯片)安装多个jdk,Mac卸载jdk
1.jdk下载 oracle官方链接:oracle官方下载链接 2.安装 直接下一步,下一步就行 3.查看是否安装成功 出现下图内容表示安装成功。 4.配置环境变量 open -e .bash_profile 路径建议复制过去 #刷新环境变量 source ~/.bash_profile 5.切换方法 6.jdk…...
Warning message:package ‘ggplot2’ is not available (for R version 3.2.3)
install.packages(ggplot2) Installing package into ‘/usr/local/lib/R/site-library’ (as ‘lib’ is unspecified) Warning message: package ‘ggplot2’ is not available (for R version 3.2.3) 根据你提供的信息,警告消息表明在你的R版本(3.2.3…...
Spring Boot 过滤器和拦截器详解
目录 Spring Boot 过滤器1.什么是过滤器2.工作机制3.实现过滤器 Spring Boot 拦截器1. 什么是拦截器2. 工作原理3.实现4.拓展(MethodInterceptor 拦截器)实现 过滤器和拦截器区别过滤器和拦截器应用场景过滤器拦截器 Spring Boot 过滤器 1.什么是过滤器 …...
Eureka介绍与使用
Eureka是一个开源的服务发现框架,由Netflix开发并在2015年成为Apache的顶级项目。Eureka的核心功能是服务注册与发现,它允许微服务应用在启动时将自己注册到Eureka服务器,并能通过Eureka服务器来发现其他已注册的服务。 使用Eureka有以下几个…...
JVM专题九:JVM分代知识点梳理
今天开始,咱们开始剖析JVM内存划分的原理细节,以及我们创建的那些对象在JVM中到底是如何分配,如何流动的,首先解决第一个问题:JVM内存的一个分代模型:年轻代、老年代、永久通过之前的专题我们知道,那就是我…...
wireshark常用过滤命令
wireshark常用过滤命令 wireshark抓包介绍单机单点:单机多点:双机并行: wireshark界面认识默认布局调整布局(常用)显示FCS错误 wireshark常见列Time回包数据报对应网络模型 wireshark基本操作结束抓包再次开始抓包 **wireshark常用过滤命令**…...
「全新升级,性能更强大——ONLYOFFICE 桌面编辑器 8.1 深度评测」
文章目录 一、背景二、界面设计与用户体验三、主要新功能亮点3.1 高效协作处理3.2 共同编辑,毫无压力3.3 批注与提及3.4 追踪更改3.5 比较与合并3.6 管理版本历史 四、性能表现4.1 集成 AI 工具4.2 插件强化 五、用户反馈与使用案例 一、背景 Ascensio System SIA -…...
线程版服务器实现(pthread_server)
用到的所有方法所需要的参数可以在wrap.c文件中查询,wrap中找不到的直接通过man手册查询 1.首先介绍一下我自己写的包裹文件,里面有各种在可能要用到的方法 wrap.c: #include <stdlib.h> #include <stdio.h> #include <unistd.h> #…...
js异常处理方案
文章目录 异常处理方案同步代码的异常处理Promise 的异常处理async await 的异常处理 感谢阅读,觉得有帮助可以点点关注点点赞,谢谢! 异常处理方案 在JS开发中,处理异常包括两步:先抛出异常,然后捕获异常。…...
C++文件路径处理2 - 路径拼接路径解析
1. 关键词2. filesystem.h3. filepath.cpp6. 测试代码7. 运行结果8. 源码地址 1. 关键词 关键词: C 文件路径处理 路径拼接 获取父目录的路径 获取文件名 获取拓展名 跨平台 应用场景: 路径的拼接路径的解析 2. filesystem.h #pragma once#include…...
数据结构5---矩阵和广义表
一、矩阵的压缩存储 特殊矩阵:矩阵中很多值相同的元素并且它们的分布有一定的规律。 稀疏矩阵:矩阵中有很多零元素。压缩存储的基本思想是: (1)为多个值相同的元素只分配一个存储空间; (2)对零元素不分配存储空间。 1、特殊矩阵的压缩存储 (1)对称矩…...
jquery使用infinitescroll无线滚动+自定义翻页
jquery版本 jquery-1.8.3.js infinitescroll版本 2.0.0 如果infinitescroll版本最新的jquery版本也要用新的 接口用nodejs jquery.infinitescroll.js官网地址 前端代码《接口返回JSON数据》 <!DOCTYPE html> <html lang"en"> <head><meta cha…...
【漏洞复现】锐捷统一上网行为管理与审计系统——远程命令执行漏洞
声明:本文档或演示材料仅供教育和教学目的使用,任何个人或组织使用本文档中的信息进行非法活动,均与本文档的作者或发布者无关。 文章目录 漏洞描述漏洞复现测试工具 漏洞描述 锐捷统一上网行为管理与审计系统naborTable/static_convert.php…...
通义灵码上线 Visual Studio 插件市场啦!
通义灵码,是阿里云出品的一款基于通义大模型的智能编码辅助工具,提供行级/函数级实时续写、自然语言生成代码、单元测试生成、代码优化、注释生成、代码解释、研发智能问答、异常报错排查等能力,提供代码智能生成、研发智能问答能力。 通义灵…...
关于nvm与node.js
1 安装nvm 安装过程中手动修改 nvm的安装路径, 以及修改 通过nvm安装node后正在使用的node的存放目录【这句话可能难以理解,但接着往下看你就了然了】 2 修改nvm中settings.txt文件配置 nvm安装成功后,通常在该文件中会出现以下配置&…...
UDP(Echoserver)
网络命令 Ping 命令 检测网络是否连通 使用方法: ping -c 次数 网址ping -c 3 www.baidu.comnetstat 命令 netstat 是一个用来查看网络状态的重要工具. 语法:netstat [选项] 功能:查看网络状态 常用选项: n 拒绝显示别名&#…...
C++ 求圆面积的程序(Program to find area of a circle)
给定半径r,求圆的面积。圆的面积应精确到小数点后5位。 例子: 输入:r 5 输出:78.53982 解释:由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982,因为我们只保留小数点后 5 位数字。 输…...
CRMEB 框架中 PHP 上传扩展开发:涵盖本地上传及阿里云 OSS、腾讯云 COS、七牛云
目前已有本地上传、阿里云OSS上传、腾讯云COS上传、七牛云上传扩展 扩展入口文件 文件目录 crmeb\services\upload\Upload.php namespace crmeb\services\upload;use crmeb\basic\BaseManager; use think\facade\Config;/*** Class Upload* package crmeb\services\upload* …...
【生成模型】视频生成论文调研
工作清单 上游应用方向:控制、速度、时长、高动态、多主体驱动 类型工作基础模型WAN / WAN-VACE / HunyuanVideo控制条件轨迹控制ATI~镜头控制ReCamMaster~多主体驱动Phantom~音频驱动Let Them Talk: Audio-Driven Multi-Person Conversational Video Generation速…...
Java + Spring Boot + Mybatis 实现批量插入
在 Java 中使用 Spring Boot 和 MyBatis 实现批量插入可以通过以下步骤完成。这里提供两种常用方法:使用 MyBatis 的 <foreach> 标签和批处理模式(ExecutorType.BATCH)。 方法一:使用 XML 的 <foreach> 标签ÿ…...
计算机基础知识解析:从应用到架构的全面拆解
目录 前言 1、 计算机的应用领域:无处不在的数字助手 2、 计算机的进化史:从算盘到量子计算 3、计算机的分类:不止 “台式机和笔记本” 4、计算机的组件:硬件与软件的协同 4.1 硬件:五大核心部件 4.2 软件&#…...
tomcat入门
1 tomcat 是什么 apache开发的web服务器可以为java web程序提供运行环境tomcat是一款高效,稳定,易于使用的web服务器tomcathttp服务器Servlet服务器 2 tomcat 目录介绍 -bin #存放tomcat的脚本 -conf #存放tomcat的配置文件 ---catalina.policy #to…...
DBLP数据库是什么?
DBLP(Digital Bibliography & Library Project)Computer Science Bibliography是全球著名的计算机科学出版物的开放书目数据库。DBLP所收录的期刊和会议论文质量较高,数据库文献更新速度很快,很好地反映了国际计算机科学学术研…...
【安全篇】金刚不坏之身:整合 Spring Security + JWT 实现无状态认证与授权
摘要 本文是《Spring Boot 实战派》系列的第四篇。我们将直面所有 Web 应用都无法回避的核心问题:安全。文章将详细阐述认证(Authentication) 与授权(Authorization的核心概念,对比传统 Session-Cookie 与现代 JWT(JS…...


new会先开辟空间再调用构造函数初始化,delete会先调用析构函数清理资源再释放空间,这点是与malloc/free的最大区别,也是C++新增用法的主要原因。
new和delete是对operator new和operator delete这两个全局函数进行的封装。所以new/delete与malloc/free的不同:malloc申请空间失败时,返回的是NULL,因此使用时必须判空,new不需要判空,申请失败会抛异常。
通过反汇编可以看到,new先调用operator new(本质上是通过malloc)来申请空间,然后再调用构造函数进行初始化;delete先调用析构函数完成资源的清理,再调用operator delete释放空间。