「C++系列」动态内存

【人工智能教程】,前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。

点击跳转到网站:【人工智能教程】

文章目录

  • 一、动态内存
    • 1. 使用`new`和`delete`
      • ①分配单个对象
      • ②分配对象数组
    • 2. 注意事项
    • 3. 智能指针
    • 4.示例:使用`std::unique_ptr`
  • 二、内存管理函数
    • 1. C语言风格的内存管理函数
    • 2. C++特有的内存管理操作符
    • 3. 智能指针
  • 三、栈内存和堆内存
    • 1. 栈内存(Stack Memory)
    • 2. 堆内存(Heap Memory)
    • 3. 注意事项
    • 4. 结论
  • 四、相关链接

一、动态内存

在C++中,动态内存管理是一个重要的概念,它允许程序在运行时根据需要分配和释放内存。这与静态内存分配(在编译时确定大小)和栈内存分配(在函数调用时自动分配和释放)不同。动态内存分配通常使用newdelete操作符(对于单个对象)或new[]delete[]操作符(对于对象数组)来完成。

1. 使用newdelete

①分配单个对象

int* ptr = new int; // 分配一个int类型的内存空间
*ptr = 10; // 使用该内存空间
delete ptr; // 释放内存
ptr = nullptr; // 避免野指针

②分配对象数组

int* arr = new int[10]; // 分配一个包含10个int的数组
for(int i = 0; i < 10; ++i) {arr[i] = i; // 初始化数组
}
delete[] arr; // 释放数组内存
arr = nullptr; // 避免野指针

2. 注意事项

  1. 内存泄漏:如果分配了内存但没有释放,那么这块内存就会一直占用,直到程序结束。这可能导致程序使用的内存不断增加,最终耗尽系统资源。

  2. 野指针:如果释放了内存但没有将指针设置为nullptr,那么这个指针就变成了野指针。尝试通过野指针访问内存是未定义行为,可能导致程序崩溃。

  3. 异常安全:在分配内存后,如果发生异常,那么可能会跳过释放内存的代码。使用智能指针(如std::unique_ptrstd::shared_ptr)可以自动管理内存,提高代码的异常安全性。

3. 智能指针

C++11及以后的版本引入了智能指针,它们可以自动管理内存,减少内存泄漏和野指针的风险。

  • std::unique_ptr:独占式拥有其所指对象,同一时间内只能有一个std::unique_ptr指向给定对象(通过禁止拷贝构造函数和拷贝赋值操作符,只提供移动语义)。

  • std::shared_ptr:允许多个std::shared_ptr实例共享同一个对象。当最后一个拥有该对象的std::shared_ptr被销毁时,对象也会被销毁。

  • std::weak_ptr:一种不拥有其所指对象的智能指针,主要用来解决std::shared_ptr之间循环引用的问题。

4.示例:使用std::unique_ptr

#include <memory>int main() {std::unique_ptr<int> ptr(new int(10));// 使用ptr...// 当ptr离开作用域时,它指向的内存会自动被释放return 0;
}

使用智能指针可以大大简化动态内存的管理,减少错误,提高代码的安全性和可维护性。

二、内存管理函数

在C++中,内存管理主要通过几种方式实现,包括使用C语言风格的内存管理函数以及C++特有的操作符和智能指针。以下是C++中常见的内存管理函数和机制:

1. C语言风格的内存管理函数

这些函数在C++中仍然可以使用,因为它们被C++继承并兼容。

  • malloc:用于动态分配指定大小的内存块。分配的内存不会自动初始化,其内容是不确定的。如果分配成功,返回指向分配的内存的指针;如果失败,返回NULL。
int* ptr = (int*)malloc(sizeof(int));
if (ptr != NULL) {// 使用ptrfree(ptr);
}
  • calloc:类似于malloc,但它会额外将分配的内存初始化为零。它接受两个参数:元素的数量和每个元素的大小。
int* arr = (int*)calloc(10, sizeof(int));
if (arr != NULL) {// 使用arrfree(arr);
}
  • realloc:用于调整之前通过malloc或calloc分配的内存块的大小。如果调整成功,返回指向新内存块的指针(可能与原指针相同,也可能不同);如果失败,返回NULL,并且原内存块保持不变。
int* new_arr = (int*)realloc(arr, 20 * sizeof(int));
if (new_arr != NULL) {arr = new_arr;// 使用arr
}
free(arr);
  • free:用于释放之前通过malloc、calloc或realloc分配的内存块。同一块内存只能被释放一次,多次释放会导致未定义行为。
free(ptr);

2. C++特有的内存管理操作符

C++引入了newdelete操作符来简化内存管理,并自动处理对象的构造和析构。

  • new:用于动态分配内存,并自动调用对象的构造函数(如果适用)。对于内置类型,它类似于malloc,但不需要类型转换。对于类类型,它还会调用构造函数。
int* ptr = new int;
MyClass* obj = new MyClass;
delete ptr;
delete obj;
  • new[]:用于动态分配一个对象数组的内存,并自动调用数组中每个对象的构造函数(如果适用)。
int* arr = new int[10];
MyClass* objs = new MyClass[5];
delete[] arr;
delete[] objs;
  • delete:用于释放之前通过new分配的内存块,并自动调用对象的析构函数(如果适用)。
  • delete[]:用于释放之前通过new[]分配的内存块,并自动调用数组中每个对象的析构函数(如果适用)。

3. 智能指针

C++11及以后的版本引入了智能指针,如std::unique_ptrstd::shared_ptrstd::weak_ptr,它们可以自动管理内存,减少内存泄漏和野指针的风险。

  • std::unique_ptr:独占式拥有其所指对象,同一时间内只能有一个std::unique_ptr指向给定对象。
  • std::shared_ptr:允许多个std::shared_ptr实例共享同一个对象。当最后一个拥有该对象的std::shared_ptr被销毁时,对象也会被销毁。
  • std::weak_ptr:一种不拥有其所指对象的智能指针,主要用来解决std::shared_ptr之间循环引用的问题。

智能指针通过封装裸指针并提供自动内存管理功能,使得C++中的动态内存管理更加安全和方便。

三、栈内存和堆内存

在C++中,内存管理是一个核心概念,它涉及到如何分配、使用和释放程序运行时所需的内存。C++程序中的内存主要分为几个区域,其中栈内存(Stack Memory)和堆内存(Heap Memory)是最常见的两种。

1. 栈内存(Stack Memory)

栈内存是自动分配和释放的内存区域。它遵循后进先出(LIFO, Last In First Out)的原则。栈内存主要用于存储局部变量、函数参数和返回值等。每当函数被调用时,它的局部变量和参数就会被推入栈中,并在函数返回时从栈中弹出。栈的大小在程序编译时就已经确定,并且通常比堆小得多。

特点

  • 自动管理:不需要程序员手动分配和释放内存。
  • 速度快:由于栈内存的操作简单且高效,访问速度非常快。
  • 有限大小:栈的大小在编译时确定,并且相对较小,可能导致栈溢出(Stack Overflow)错误。

2. 堆内存(Heap Memory)

堆内存是动态分配和释放的内存区域。与栈内存不同,堆内存的大小不是固定的,它可以在程序运行时根据需要动态地增长和缩小。堆内存主要用于存储那些大小在程序编译时未知的对象,或者需要在程序的不同部分之间共享的数据。堆内存的分配和释放需要程序员手动管理,通常使用newdelete操作符(对于单个对象)或new[]delete[]操作符(对于对象数组)来完成。

特点

  • 手动管理:程序员需要负责分配和释放内存,这增加了内存泄漏和野指针的风险。
  • 灵活:堆内存的大小可以在运行时动态变化,适合存储大小未知或变化的数据。
  • 相对较慢:与栈内存相比,堆内存的分配和释放操作更复杂,因此访问速度相对较慢。

3. 注意事项

  • 内存泄漏:在堆上分配的内存如果没有被正确释放,就会导致内存泄漏。随着时间的推移,这可能会耗尽系统的可用内存。
  • 野指针:如果释放了堆上的内存但没有将指针设置为nullptr,那么这个指针就变成了野指针。尝试通过野指针访问内存是未定义行为,可能导致程序崩溃。
  • 栈溢出:如果栈上的局部变量太多或太大,就可能导致栈溢出错误。这通常发生在递归调用过深或局部变量占用大量内存时。

4. 结论

栈内存和堆内存各有优缺点,适用于不同的场景。栈内存适合存储局部变量和函数参数等小量数据,而堆内存则适合存储大量或动态变化的数据。在使用堆内存时,程序员需要格外注意内存的管理,以避免内存泄漏和野指针等问题。

在这里插入图片描述

四、相关链接

  1. Visual Studio Code下载地址
  2. Sublime Text下载地址
  3. 「C++系列」C++简介、应用领域
  4. 「C++系列」C++ 基本语法
  5. 「C++系列」C++ 数据类型
  6. 「C++系列」C++ 变量类型
  7. 「C++系列」C++ 变量作用域
  8. 「C++系列」C++ 常量知识点-细致讲解
  9. 「C++系列」C++ 修饰符类型
  10. 「C++系列」一篇文章说透【存储类】
  11. 「C++系列」一篇文章讲透【运算符】
  12. 「C++系列」循环
  13. 「C++系列」判断
  14. 「C++系列」函数/内置函数
  15. 「C++系列」数字/随机数
  16. 「C++系列」数组
  17. 「C++系列」字符串
  18. 「C++系列」指针
  19. 「C++系列」引用
  20. 「C++系列」日期/时间
  21. 「C++系列」输入/输出
  22. 「C++系列」数据结构
  23. 「C++系列」vector 容器
  24. 「C++系列」类/对象
  25. 「C++系列」继承
  26. 「C++系列」重载运算符/重载函数
  27. 「C++系列」多态
  28. 「C++系列」数据抽象
  29. 「C++系列」数据封装
  30. 「C++系列」 接口(抽象类)
  31. 「C++系列」文件和流
  32. 「C++系列」异常处理

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

python全栈学习记录(十七)logging、json与pickle、time与datatime、random

logging、json与pickle、time与datatime、random 文章目录 logging、json与pickle、time与datatime、random一、logging二.json与pickle三.time与datatime四.random 一、logging logging模块用来记录日志信息。 import logging # 进行基本的日志配置 logging.basicConfig( fi…

图文深入理解SQL语句的执行过程

List item 本文将深入介绍SQL语句的执行过程。 一.在RDBMS&#xff08;关系型DB&#xff09;中&#xff0c;看似很简单的一条已写入DB内存的SQL语句执行过程却非常复杂&#xff0c;也就是说&#xff0c;你执行了一条诸如select count(*) where id 001 from table_name的非常简…

[WMCTF2020]Make PHP Great Again 2.01

又是php代码审计,开始吧. 这不用审吧&#xff0c;啊喂. 意思就是我们要利用require_once()函数和传入的file的value去读取flag的内容.&#xff0c;貌似呢require_once()已经被用过一次了&#xff0c;直接读取还不行&#xff0c;看一下下面的知识点. require_once() require…

WebLogic 漏洞复现

1、后台弱⼝令GetShell 默认账号密码&#xff1a;weblogic/Oracle123 weblogic常⽤弱⼝令&#xff1a;https://cirt.net/passwords?criteriaweblogic 这⾥注意&#xff0c; 单个账号错误密码5次之后就会⾃动锁定。 http://47.121.212.195:7001/console 2、登录后台后&#…

恒生科指八连涨,汽车股强势

9月20日电 周五&#xff0c;港股三大股指集体收涨。恒生指数涨1.36%报18258.57点&#xff0c;连续第六个交易日上涨&#xff1b;恒生科技指数涨1.43%报3703.84点&#xff0c;连续第八个交易日上涨&#xff0c;创逾两个月来新高&#xff1b;恒生中国企业指数涨1.21%报6381.5点&a…

项目扩展五:交互式:command-line interface版本的实现

项目扩展五&#xff1a;command-line interface版本的实现 一、CLI交互的设计1.为何要设计这个CLI交互2.具体设计1.启动服务2.选择信道3.选择虚拟机4.正式业务注意&#xff1a;1.消费者与生产者跟信道的关系2.消息处理回调函数的问题3.消息确认的问题 5.其他功能1.打印功能2.查…

STM32精确控制步进电机

目的&#xff1a;学习使用STM32电机驱动器步进电机&#xff0c;进行电机运动精确控制。 测试环境&#xff1a; MCU主控芯片STM32F103RCT6 &#xff1b;A4988步进电机驱动器模块&#xff1b;微型2相4线步进电机10mm丝杆滑台&#xff0c;金属丝杆安装有滑块。 10mm二相四线微型…

机器学习之非监督学习(二)异常检测(基于高斯概率密度)

机器学习之非监督学习&#xff08;二&#xff09;异常检测&#xff08;基于高斯概率密度&#xff09; 0. 文章传送1.案例引入2.高斯正态分布3.异常检测算法4.异常检测 vs 监督学习5.算法优化6.代码实现 0. 文章传送 机器学习之监督学习&#xff08;一&#xff09;线性回归、多…

C语言中数组和字符串的联系

一、C语言中&#xff0c;数组和字符串 1、C语言中&#xff0c;定义一个数组后&#xff0c;数组名保存的是这个数组的首地址。类似一个指向数组第一个元素的指针&#xff0c;但是这个指针不能重新指向。2、字符串在C语言中是通过字符数组来实现的&#xff0c;也就是说字符串还是…

【小沐学CAD】3ds Max常见操作汇总

文章目录 1、简介2、二次开发2.1 C 和 3ds Max C SDK2.2 NET 和 3ds Max .NET API2.3 3ds Max 中的 Python 脚本2.4 3ds Max 中的 MAXScript 脚本 3、快捷键3.1 3Dmax键快捷键命令——按字母排序3.2 3dmax快捷键命令——数字键3.3 3dmax功能键快捷键命令3.4 3Dmax常用快捷键——…

Elasticsearch 完整格式的 URL 进行分词,有什么好的解决方案吗?

1、问题描述 我想对完整格式的 url 进行分词&#xff0c;请问有什么好的解决方案吗&#xff1f; 比如&#xff1a;https://www.abc.com/any/path?param_1some&param-2other#title 看了官方的分词器&#xff0c;感觉没啥合适的? 预处理的话&#xff0c;又不知道该怎么处理…

Unity对象池的高级写法 (Plus优化版)

唐老师关于对物体分类的OOD的写法确实十分好&#xff0c;代码也耦合度也低&#xff0c;但是我有个简单的写法同样能实现一样的效果&#xff0c;所以我就充分发挥了一下主观能动性 相较于基本功能&#xff0c;这一版做出了如下改动 1.限制了对象池最大数量&#xff0c;多出来的…

C++11 可变的模板参数

前言 本期我们接着继续介绍C11的新特性&#xff0c;本期我们介绍的这个新特性是很多人都感觉抽象的语法&#xff01;它就是可变的模板参数&#xff01; 目录 前言 一、可变的模板参数 1.1可变的参数列表 1.2可变的参数包 1.3可变参数包的解析 • 递归展开解析 • 逗号…

微服务Docker相关指令

1、拉取容器到镜像仓库 docker pull xxx //拉取指令到 镜像仓库 例如 docker pull mysql 、docker pull nginx docker images //查看镜像仓库 2、删除资源 2.1、删除镜像仓库中的资源 docker rmi mysql:latest //删除方式一&#xff1a;格式 docker rmi 要…

【解密 Kotlin 扩展函数】扩展函数的创建(十六)

导读大纲 1.1 为第三方的类添加方法: 扩展函数 1.1 为第三方的类添加方法: 扩展函数 Kotlin 的主题之一是与现有代码的平滑集成 即使是纯 Kotlin 项目,也是构建在 Java 库之上的 如 JDK、Android 框架和其他第三方框架 而当你将 Kotlin 集成到 Java 项目中时 你还要处理尚未或不…

python爬虫:将知乎专栏文章转为pdf

欢迎关注本人的知乎主页~ 实现思路 用户输入专栏ID&#xff1a; 代码首先提示用户输入一个知乎专栏的ID&#xff0c;默认值为 c_1747690982282477569。输入的ID用于构建API请求的URL。 发送HTTP请求&#xff1a; 使用 requests.get() 向知乎API发送GET请求&#xff0c;获取指定…

【QGIS入门实战精品教程】6.1:QGIS根据属性条件查询数据(SQL表达式)

文章目录 一、字段过滤二、高级过滤(表达式)一、字段过滤 对于单个字段的查询,可以采用字段过滤,例如,从县区数据中,根据NAME字段,查找出县级市玉门市。操作为:右键县区→打开属性表: 点击左下角,选择name字段。 输入玉门市,回车,选择查找除的属性表记录,此时图斑…

【Linux】入门【更详细,带实操】

Linux全套讲解系列&#xff0c;参考视频-B站韩顺平&#xff0c;本文的讲解更为详细 目录 1、课程内容 2、应用领域 3、概述 4、 Linux和Unix 5、VMware15.5和CentOS7.6安装 6、网络连接三种方式 7、虚拟机克隆 8、虚拟机快照 9、虚拟机迁移删除 10、vmtools 11、目录…

set-ExecutionPolicy RemoteSigned 提示不是内部或外部命令,也不是可运行的程序或批处理文件

这个错误一般发生在使用命令提示符或者PowerShell窗口中找不到set-ExecutionPolicy RemoteSigned。如果你想在命令提示符或者PowerShell窗口运行set-ExecutionPolicy RemoteSigned&#xff0c;你需要搜索打开Window PowerShell ISE&#xff0c;并以管理员身份打开&#xff0c;输…

基于微信小程序的美食外卖管理系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码 精品专栏&#xff1a;Java精选实战项目…