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

「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++系列」异常处理

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 超越sora,最新文生视频CogVideoX-5b模型分享
  • ChatGPT 在国内使用的方法
  • aws 容器镜像仓库操作
  • 数据结构——二叉搜索树
  • Java调用数据库 笔记05(查询篇)
  • 植物大战僵尸【源代码分享+核心思路讲解】
  • 【MySQL】获取最近7天和最近14天的订单数量,使用MySQL详细写出,使用不同的方法
  • openeuler 22.03 lts sp4 使用 kubeadm 部署 k8s-v1.28.2 高可用集群
  • CTF 技能树 LOG -GIT泄露 笔记
  • 身份安全风险不断上升:企业为何必须立即采取行动
  • Nginx反向代理出现502 Bad Gateway问题的解决方案
  • ES学习笔记
  • 制作一个rabbitmq-sdk以及rabbitmq消费者实现定时上下线功能
  • 怎么让Nginx可以访问某一IP的每个后台controller接口
  • Html css样式总结
  • Android Studio:GIT提交项目到远程仓库
  • Android 控件背景颜色处理
  • Angular6错误 Service: No provider for Renderer2
  • Fabric架构演变之路
  • Java读取Properties文件的六种方法
  • Laravel Telescope:优雅的应用调试工具
  • swift基础之_对象 实例方法 对象方法。
  • V4L2视频输入框架概述
  • 从PHP迁移至Golang - 基础篇
  • 从地狱到天堂,Node 回调向 async/await 转变
  • 首页查询功能的一次实现过程
  • 算法---两个栈实现一个队列
  • 问题之ssh中Host key verification failed的解决
  • 远离DoS攻击 Windows Server 2016发布DNS政策
  • 06-01 点餐小程序前台界面搭建
  • 如何在招聘中考核.NET架构师
  • ​iOS安全加固方法及实现
  • ​低代码平台的核心价值与优势
  • (java版)排序算法----【冒泡,选择,插入,希尔,快速排序,归并排序,基数排序】超详细~~
  • (Java企业 / 公司项目)点赞业务系统设计-批量查询点赞状态(二)
  • (超简单)使用vuepress搭建自己的博客并部署到github pages上
  • (附源码)ssm基于微信小程序的疫苗管理系统 毕业设计 092354
  • (每日持续更新)信息系统项目管理(第四版)(高级项目管理)考试重点整理第3章 信息系统治理(一)
  • (十八)SpringBoot之发送QQ邮件
  • (转)Unity3DUnity3D在android下调试
  • *(长期更新)软考网络工程师学习笔记——Section 22 无线局域网
  • ..回顾17,展望18
  • .bashrc在哪里,alias妙用
  • .net core 依赖注入的基本用发
  • .NET 使用配置文件
  • .NET 依赖注入和配置系统
  • .NET/C# 获取一个正在运行的进程的命令行参数
  • .Net环境下的缓存技术介绍
  • .NET精简框架的“无法找到资源程序集”异常释疑
  • .net知识和学习方法系列(二十一)CLR-枚举
  • @Autowired 和 @Resource 区别的补充说明与示例
  • @data注解_SpringBoot 使用WebSocket打造在线聊天室(基于注解)
  • [ linux ] linux 命令英文全称及解释
  • []利用定点式具实现:文件读取,完成不同进制之间的
  • [23] 4K4D: Real-Time 4D View Synthesis at 4K Resolution