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

学懂C++ (十四):高级教程——C++ 动态内存管理(new和delete)详解

        在C++编程中,动态内存管理是一个重要的概念,它使得程序在运行时可以根据实际需要分配和释放内存。这种能力特别适用于在编译时无法确定所需内存大小的情况,如处理动态数据结构(例如链表、树)或根据用户输入进行数据处理等。

内存区域概述

C++程序中的内存分为两个主要部分:

  • 栈(Stack):用于存储局部变量,函数调用时的参数等。栈内存由系统自动管理,在函数返回时自动释放。
  • 堆(Heap):用于动态分配内存,程序员可以在运行时申请和释放这部分内存。

动态内存分配与释放

C++提供了newdelete运算符,用于在堆中分配和释放内存。使用new运算符可以在堆中为变量动态分配内存,而使用delete运算符可以释放这些内存。

1. 动态分配内存:new运算符

new运算符用于在堆中动态分配内存,并返回一个指向该内存的指针。

int* ptr = new int; // 为一个int类型的变量分配内存
2. 释放内存:delete运算符

delete运算符用于释放之前通过new分配的内存。

delete ptr; // 释放指针ptr指向的内存

数组的动态内存分配

使用new可以为数组动态分配内存。

int* arr = new int[10]; // 为一个包含10个整数的数组分配内存
delete[] arr; // 释放数组内存

多维数组的动态内存分配

C++允许为多维数组动态分配内存。下面是为二维和三维数组动态分配内存的示例。

二维数组

int** array = new int*[m]; // 为m行分配内存
for(int i = 0; i < m; i++) {array[i] = new int[n]; // 为每行分配n列内存
}// 使用数组...for(int i = 0; i < m; i++) {delete[] array[i]; // 释放每行的内存
}
delete[] array; // 释放行指针数组的内存

三维数组

int*** array = new int**[m];
for(int i = 0; i < m; i++) {array[i] = new int*[n];for(int j = 0; j < n; j++) {array[i][j] = new int[h];}
}// 使用数组...for(int i = 0; i < m; i++) {for(int j = 0; j < n; j++) {delete[] array[i][j]; // 释放每个二维数组}delete[] array[i]; // 释放每行的指针数组
}
delete[] array; // 释放行指针数组的内存

对象的动态内存分配

newdelete同样适用于对象。为对象分配内存时,会调用构造函数,释放内存时,会调用析构函数。

class Box {
public:Box() { cout << "调用构造函数!" << endl; }~Box() { cout << "调用析构函数!" << endl; }
};int main() {Box* myBox = new Box; // 动态分配Box对象,调用构造函数delete myBox; // 释放内存,调用析构函数Box* myBoxArray = new Box[4]; // 动态分配Box对象数组,调用4次构造函数delete[] myBoxArray; // 释放数组内存,调用4次析构函数return 0;
}

delete[] 和delete的区别

在C++中,deletedelete[]都是用于释放通过newnew[]运算符动态分配的内存。然而,它们之间有一个重要的区别:delete用于释放单个对象的内存,而delete[]用于释放数组的内存。

delete的使用

delete运算符用于释放通过new运算符分配的单个对象。

int* ptr = new int; // 动态分配一个int类型的对象
delete ptr; // 释放这个对象的内存

当使用delete时,会调用指针指向对象的析构函数(如果有),然后释放内存。

delete[]的使用

delete[]运算符用于释放通过new[]运算符分配的数组。

int* arr = new int[10]; // 动态分配一个包含10个int的数组
delete[] arr; // 释放这个数组的内存

当使用delete[]时,会调用数组中每个对象的析构函数(如果有),然后释放整个数组的内存。

为什么需要区别对待?

C++需要区分deletedelete[]是因为编译器需要知道它是在释放单个对象还是多个对象,以便正确地调用相应的析构函数。

  • 对于单个对象:编译器只需要调用一次析构函数并释放内存。
  • 对于数组:编译器需要调用数组中每个对象的析构函数,然后释放整个数组的内存。

如果错误地使用delete来释放数组内存,或者使用delete[]来释放单个对象内存,结果是未定义的行为,可能会导致程序崩溃或其他不可预测的问题。

  • delete:用于释放通过new分配的单个对象。
  • delete[]:用于释放通过new[]分配的数组。

常见的动态内存管理问题

  • 内存泄漏:如果程序没有释放通过new分配的内存,将导致内存泄漏。内存泄漏会逐渐耗尽系统资源,导致程序或系统的性能下降。
  • 野指针:释放内存后指针仍然指向该内存,称为野指针。访问野指针指向的内存会导致未定义行为。

总结

动态内存管理是C++编程中的重要概念,它使得程序可以在运行时根据实际需求灵活地管理内存。使用newdelete运算符进行内存分配和释放时,程序员需要特别小心,以避免内存泄漏和其他内存管理问题。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • Cmake基础教程--第1章:初识cmake
  • python实现返回指定下标位置的 斐波那契数列[1,1,2,3,5,8,13,21,34....n] 数值
  • 基于Springboot + Vue的宿舍管理系统
  • 思特威正式发布子品牌飞凌微,首发产品定位智驾视觉处理
  • chromedriver版本下载地址汇总chromedriver所有版本下载地址汇总国内源下载
  • 在 Mac 上恢复永久删除的文件:分步指南
  • 谷粒商城实战笔记-117-全文检索-ElasticSearch-进阶-term查询
  • 本地部署 Llama-3-EvoVLM-JP-v2
  • 分布式事务一站式解决方案-Seata
  • 【OpenCV C++20 学习笔记】物体检测-Ballard和Guil霍夫变换
  • 常见框架漏洞 上 (Thinkphp、struts2、Spring、Shiro)
  • Linux中NFS配置
  • 【实现100个unity特效之15】最简单的方法使用shader graphs实现2d非像素和像素树叶草的随风摇摆效果
  • 在Linux上安装Conda以支持Go 1.19
  • 快速体验LLaMA-Factory 私有化部署和高效微调Llama3模型(曙光超算互联网平台异构加速卡DCU)
  • [分享]iOS开发-关于在xcode中引用文件夹右边出现问号的解决办法
  • es6--symbol
  • laravel5.5 视图共享数据
  • LeetCode算法系列_0891_子序列宽度之和
  • Logstash 参考指南(目录)
  • mysql_config not found
  • webpack+react项目初体验——记录我的webpack环境配置
  • 不上全站https的网站你们就等着被恶心死吧
  • 互联网大裁员:Java程序员失工作,焉知不能进ali?
  • 吐槽Javascript系列二:数组中的splice和slice方法
  • 与 ConTeXt MkIV 官方文档的接驳
  • 字符串匹配基础上
  • No resource identifier found for attribute,RxJava之zip操作符
  • Prometheus VS InfluxDB
  • #if和#ifdef区别
  • #ubuntu# #git# repository git config --global --add safe.directory
  • (1)Android开发优化---------UI优化
  • (C语言)二分查找 超详细
  • (zz)子曾经曰过:先有司,赦小过,举贤才
  • (八)Docker网络跨主机通讯vxlan和vlan
  • (附源码)SSM环卫人员管理平台 计算机毕设36412
  • (附源码)ssm智慧社区管理系统 毕业设计 101635
  • (每日一问)操作系统:常见的 Linux 指令详解
  • (推荐)叮当——中文语音对话机器人
  • (一)SvelteKit教程:hello world
  • (一)u-boot-nand.bin的下载
  • .net core webapi Startup 注入ConfigurePrimaryHttpMessageHandler
  • .net core开源商城系统源码,支持可视化布局小程序
  • .NET 设计模式—适配器模式(Adapter Pattern)
  • .net下的富文本编辑器FCKeditor的配置方法
  • /bin、/sbin、/usr/bin、/usr/sbin
  • ??如何把JavaScript脚本中的参数传到java代码段中
  • @EnableWebMvc介绍和使用详细demo
  • @ModelAttribute注解使用
  • []error LNK2001: unresolved external symbol _m
  • []Telit UC864E 拨号上网
  • [000-01-030].Zookeeper学习大纲
  • [1159]adb判断手机屏幕状态并点亮屏幕
  • [2010-8-30]
  • [AI Google] 使用 Gemini 取得更多成就:试用 1.5 Pro 和更多智能功能