【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 插件市场啦!
通义灵码,是阿里云出品的一款基于通义大模型的智能编码辅助工具,提供行级/函数级实时续写、自然语言生成代码、单元测试生成、代码优化、注释生成、代码解释、研发智能问答、异常报错排查等能力,提供代码智能生成、研发智能问答能力。 通义灵…...
大语言模型如何处理长文本?常用文本分割技术详解
为什么需要文本分割? 引言:为什么需要文本分割?一、基础文本分割方法1. 按段落分割(Paragraph Splitting)2. 按句子分割(Sentence Splitting)二、高级文本分割策略3. 重叠分割(Sliding Window)4. 递归分割(Recursive Splitting)三、生产级工具推荐5. 使用LangChain的…...
AspectJ 在 Android 中的完整使用指南
一、环境配置(Gradle 7.0 适配) 1. 项目级 build.gradle // 注意:沪江插件已停更,推荐官方兼容方案 buildscript {dependencies {classpath org.aspectj:aspectjtools:1.9.9.1 // AspectJ 工具} } 2. 模块级 build.gradle plu…...
Linux --进程控制
本文从以下五个方面来初步认识进程控制: 目录 进程创建 进程终止 进程等待 进程替换 模拟实现一个微型shell 进程创建 在Linux系统中我们可以在一个进程使用系统调用fork()来创建子进程,创建出来的进程就是子进程,原来的进程为父进程。…...
laravel8+vue3.0+element-plus搭建方法
创建 laravel8 项目 composer create-project --prefer-dist laravel/laravel laravel8 8.* 安装 laravel/ui composer require laravel/ui 修改 package.json 文件 "devDependencies": {"vue/compiler-sfc": "^3.0.7","axios": …...
Java毕业设计:WML信息查询与后端信息发布系统开发
JAVAWML信息查询与后端信息发布系统实现 一、系统概述 本系统基于Java和WML(无线标记语言)技术开发,实现了移动设备上的信息查询与后端信息发布功能。系统采用B/S架构,服务器端使用Java Servlet处理请求,数据库采用MySQL存储信息࿰…...
【电力电子】基于STM32F103C8T6单片机双极性SPWM逆变(硬件篇)
本项目是基于 STM32F103C8T6 微控制器的 SPWM(正弦脉宽调制)电源模块,能够生成可调频率和幅值的正弦波交流电源输出。该项目适用于逆变器、UPS电源、变频器等应用场景。 供电电源 输入电压采集 上图为本设计的电源电路,图中 D1 为二极管, 其目的是防止正负极电源反接, …...
使用LangGraph和LangSmith构建多智能体人工智能系统
现在,通过组合几个较小的子智能体来创建一个强大的人工智能智能体正成为一种趋势。但这也带来了一些挑战,比如减少幻觉、管理对话流程、在测试期间留意智能体的工作方式、允许人工介入以及评估其性能。你需要进行大量的反复试验。 在这篇博客〔原作者&a…...
苹果AI眼镜:从“工具”到“社交姿态”的范式革命——重新定义AI交互入口的未来机会
在2025年的AI硬件浪潮中,苹果AI眼镜(Apple Glasses)正在引发一场关于“人机交互形态”的深度思考。它并非简单地替代AirPods或Apple Watch,而是开辟了一个全新的、日常可接受的AI入口。其核心价值不在于功能的堆叠,而在于如何通过形态设计打破社交壁垒,成为用户“全天佩戴…...
从面试角度回答Android中ContentProvider启动原理
Android中ContentProvider原理的面试角度解析,分为已启动和未启动两种场景: 一、ContentProvider已启动的情况 1. 核心流程 触发条件:当其他组件(如Activity、Service)通过ContentR…...
Spring AOP代理对象生成原理
代理对象生成的关键类是【AnnotationAwareAspectJAutoProxyCreator】,这个类继承了【BeanPostProcessor】是一个后置处理器 在bean对象生命周期中初始化时执行【org.springframework.beans.factory.config.BeanPostProcessor#postProcessAfterInitialization】方法时…...


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释放空间。