C/C++ - 内存管理(C++)

news2024/12/25 12:54:05

堆栈

  • C++中的栈和堆是用于存储变量和对象​​的两个主要内存区域。
  • 栈是一种自动分配和释放内存的区域,用于存储局部变量和函数调用的上下文。栈上的内存分配和释放是自动进行的,无需手动管理。
  • 堆是动态分配内存的区域,用于存储动态创建的对象和数据结构。
  • 堆上的内存分配和释放需要手动进行,通过使用 new / malloc​​ 和 delete / free​​ 运算符或者使用智能指针等机制。
  • 堆(Heap)

    • 堆是在程序运行时动态分配内存的区域,用于存储动态创建的对象和数据结构。

    • 在堆上分配的内存需要手动进行管理,通过使用 new​​​ 和 delete​​​ 运算符或者智能指针​​等机制进行内存的分配和释放。

    • 堆上的内存可以在任何时候进行分配和释放,而不受作用域的限制。

      int* ptr = new int;  // 动态分配一个整型内存块
      *ptr = 5;
      delete ptr;  // 释放内存
      
  • 栈(tack)

    • 栈是基于线程而言的,每条线程都有属于自己的栈区。

    • 栈是一种自动分配和释放内存的区域,用于存储局部变量和函数调用的上下文。

    • 栈上的内存分配和释放是自动进行的,无需手动管理。

    • 栈上的内存分配和释放遵循“先进后出”的原则,即最后进入栈的变量最先离开。

      void foo() 
      {
          int x = 5;  // 在栈上分配整型变量
          // ...
      }  // 函数结束,栈上的变量自动释放
      
  • 栈上分配的内存特点

    • 栈上分配的内存空间相对较小,受限于编译器和操作系统的设置。通常在几兆字节到几十兆字节之间。
    • 栈上的内存分配和释放速度较快,仅涉及移动栈指针。
    • 栈上的内存分配是按照严格的顺序进行的,无法随机访问。
  • 堆和栈的比较

    • 堆和栈都是用于存储数据的内存区域,但它们有不同的特点和用途。
    • 堆适用于动态分配内存,可以在任何时候进行分配和释放,适用于需要灵活管理内存的情况。
    • 栈适用于自动分配和释放内存,适用于局部变量和函数调用的上下文。

内存

  • new

    • 动态分配单个对象

      • 使用new​​​​运算符可以在堆上动态分配单个对象的内存,并返回指向该内存的指针。

      • 语法:new 类名;​​​​ 或 new 类名(参数);​​​​

        int* ptr = new int;  // 动态分配一个整型对象
        *ptr = 5;  // 对分配的内存进行操作
        delete ptr;  // 释放内存
        
    • 底层执行

    • 动态分配对象数组:

      • 使用new​​​​运算符可以在堆上动态分配对象数组的内存,并返回指向该内存的指针。

      • 语法:new 类名[数组大小];​​​​

        int* arr = new int[5];  // 动态分配一个包含5个整型元素的数组
        for (int i = 0; i < 5; ++i) 
        {
            arr[i] = i;
        }
        delete[] arr;  // 释放内存
        
  • delete

    • 释放单个对象内存:

      • 使用delete​​运算符可以释放通过new​​运算符分配的单个对象的内存。

      • 语法:delete 指针;​​

        int* ptr = new int;  // 动态分配一个整型对象
        *ptr = 5;
        delete ptr;  // 释放内存
        
    • 释放对象数组内存:

      • 使用delete[]​​运算符可以释放通过new​​运算符分配的对象数组的内存。

      • 语法:delete[] 指针;​​

        #include <iostream>
        
        
        int main()
        {
        	//new    - malloc
        	//delete - free
        
        	//C
        	int* p1 = (int*)malloc(sizeof(int));
        	if (p1)
        	{
        		free(p1);
        		p1 = NULL;
        	}
        
        	int* p2 = (int*)malloc(sizeof(int) * 10);
        	if (p2)
        	{
        		free(p2);
        		p2 = NULL;
        	}
        
        	//CPP
        	int* p3 = new int;
        	if (p3)
        	{
        		delete p3;
        		p3 = NULL;
        	}
        
        	int* p4 = new int(10);
        	if (p4)
        	{
        		delete p4;
        		p4 = NULL;
        	}
        
        	int* p5 = new int[10];
        	if (p5)
        	{
        		delete[] p5;
        		p5 = NULL;
        	}
        
        	return 0;
        }
        
  • 内存失败处理

    • 在使用new​​运算符分配内存时,如果内存不足或分配失败,会抛出std::bad_alloc​​异常。因此,需要在代码中适当处理异常情况

    • 可以使用try-catch​​语句块来捕获并处理异常。

      #include <iostream>
      
      
      void Exception_CPP()
      {
      	try
      	{
      		//可能会出现错误的代码
      		long long* p = new long long[0xFFFFFFF];
      		delete[] p;
      	}
      	catch (const std::exception& Error)
      	{
      		//出现异常捕获处理异常
      		std::cout << "Exception ->" << Error.what() << std::endl;
      	}
      
      }
      
      int main()
      {
      	Exception_CPP();
      
      	return 0;
      }
      

智能指针

  • 在C++中,智能指针是一种用于管理动态分配的内存资源的工具。它们以对象的形式封装了原始指针,并提供了自动化的内存管理和资源释放,从而减少内存泄漏和悬挂指针等问题。
  • 智能指针主要有两种类型:shared_ptr​​和unique_ptr​​。
  • ​shared_ptr

    • ​shared_ptr​​是一种引用计数智能指针,用于多个指针共享同一个对象。它会跟踪有多少个shared_ptr​​指向同一块内存,并在不再需要时自动释放该内存。

    • 创建

      • std::shared_ptr<int> ptr = std::make_shared<int>(42);
        
    • 引用计数

      • std::shared_ptr<int> ptr1 = std::make_shared<int>(42);
        std::shared_ptr<int> ptr2 = ptr1; // 引用计数递增
        
        std::cout << ptr1.use_count() << std::endl; // 输出2,引用计数为2
        
    • 解引用

      • std::shared_ptr<int> ptr = std::make_shared<int>(42);
        std::cout << *ptr << std::endl; // 输出42
        
    • 重置指针

      • std::shared_ptr<int> ptr = std::make_shared<int>(42);
        ptr.reset(); // 释放资源,引用计数减少
        
        if (ptr == nullptr) {
            std::cout << "智能指针为空" << std::endl;
        }
        
  • ​​unique_ptr

    • ​​unique_ptr​​是一种独占式智能指针,用于唯一地拥有一个对象。它提供了对动态分配的内存的所有权,并在不再需要时自动释放该内存。

    • 创建

      • std::unique_ptr<int> ptr = std::make_unique<int>(42);
        
    • ​​移动语义​

      • std::unique_ptr<int> ptr1 = std::make_unique<int>(42);
        std::unique_ptr<int> ptr2 = std::move(ptr1); // 移动语义,ptr1不再拥有资源
        
        if (ptr1 == nullptr) 
        {
            std::cout << "ptr1不再拥有资源" << std::endl;
        }
        
    • 解引用

      • std::unique_ptr<int> ptr = std::make_unique<int>(42);
        std::cout << *ptr << std::endl; // 输出42
        
    • 释放资源

      • std::unique_ptr<int> ptr = std::make_unique<int>(42);
        ptr.release(); // 释放资源,但不销毁指针
        
        if (ptr == nullptr) 
        {
            std::cout << "unique_ptr已释放资源" << std::endl;
        }
        

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

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

相关文章

Blender教程(基础)-内插面、分离、环切、倒角-08

一、内插面 菜单位置如下图位置。 单击需要处理的面&#xff0c;出现一个黄色的圈。 1、菜单选中内插 鼠标悬停在黄色圈内单击左键可以来回实现内插&#xff0c;但是发现并不好操作。 2、快捷键内插 在选中需要操作的面之后&#xff0c;鼠标移动到外面&#xff0c;键盘在英…

计算机设计大赛 基于图像识别的跌倒检测算法

前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 基于图像识别的跌倒检测算法 该项目较为新颖&#xff0c;适合作为竞赛课题方向&#xff0c;学长非常推荐&#xff01; &#x1f9ff; 更多资料, 项目分享&#xff1a; https://gitee.com/dancheng-senior/…

Java图形化界面基本案例

案例&#xff1a; public class exer1 {JFrame snew JFrame("练习");//菜单JMenuBar jMenuBarnew JMenuBar();JMenu wenjiannew JMenu("文件");JMenu bianjinew JMenu("编辑");JMenuItem zidongnew JMenuItem("自动换行");JMenuItem f…

斜率优化dp模型整理

300. 任务安排1&#xff08;300. 任务安排1 - AcWing题库&#xff09; 思路&#xff1a;很明显这些任务是按顺序排好的&#xff0c;我们能执行的操作只是对它们进行分批&#xff0c;我们可以发现每一批之前的开始时间s&#xff0c;影响的不仅仅是当前这一批的结束时间&#xff…

Java强训day9(选择题编程题)

选择题 class Person {String name "No name";public Person(String nm) {name nm;} } class Employee extends Person {String empID "0000";public Employee(String id) {super(" ");//要调用父类的有参构造方法否则报错empID id;} } pu…

常用芯片学习——AMS1117芯片

AMS1117 1A 低压差线性稳压器 使用说明 AMS1117 是一款低压差线性稳压电路&#xff0c;该电路输出电流能力为1A。该系列电路包含固定输出电压版本和可调输出电压版本&#xff0c;其输出电压精度为士1.5%。为了保证芯片和电源系统的稳定性&#xff0c;XBLWAMS1117 内置热保护和…

秋招面试—浏览器原理篇

浏览器原理篇 1.什么是XSS、CSRF,怎么预防&#xff1f; &#xff08;1&#xff09;XSS(跨站脚本攻击)&#xff1a;攻击者将恶意代码植入到浏览器页面中&#xff0c;盗取存储在客户端的Cookie&#xff1b; ​ XSS分为&#xff1a;①存储型&#xff1a;论坛发帖、商品评论、用户…

大型电商系统商城源码_架构_订单系统_OctShop

中国的电商差不多发展到今天已经有20多年的历史啦&#xff0c;特别是过去的10年里其发展速度与竞争是相当的激烈&#xff0c;发展出了各种各样的模式如&#xff1a;B2B、B2C、B2B2C、O2O、社交电商等等。对于广大的企业或商家来说&#xff0c;电商是一个不可或缺的销售渠道&…

猫咪不吃东西怎么办?公认适口性好的生骨肉冻干分享

猫咪不吃东西怎么办&#xff1f;遇到这类情况主人需要仔细观察并分析情况。如果猫咪出现其他异常症状&#xff0c;如呕吐、腹泻、体温异常等&#xff0c;可能是生病了&#xff0c;应及时就医。如果猫咪没有其他异常症状&#xff0c;那猫咪不吃东西怎么办&#xff1f;可能是猫粮…

JAVA多线程并发补充

AQS 是一个抽象父类 全称是 AbstractQueuedSynchronizer&#xff0c;是阻塞式锁和相关的同步器工具的框架。 用 state 属性来表示资源的状态&#xff08;分独占模式和共享模式&#xff09;&#xff0c;子类需要定义如何维护这个状态&#xff0c;控制如何获取锁和释放锁 getSt…

Windows系统云服务器自定义域名解析导致网站无法访问怎么解决?

本文九河云介绍Windows实例内部自定义域名解析与本地网络域名解析不一致导致无法访问网站的问题描述、问题原因和解决方案。 问题描述 在Windows实例内部通过浏览器无法访问某网站&#xff0c;但在其他设备上可以正常访问&#xff0c;排查发现Windows实例内部自定义域名解析与…

6.s081 学习实验记录(三)system calls

文章目录 一、use gdb二、syscall&#xff1a;trace注意&#xff1a;实验代码&#xff1a;实验结果&#xff1a; 三、sysinfotips&#xff1a;实验代码实验结果 需要切换到 syscall 分支 一、use gdb 学习使用 gdb 调试 make qemu-gdb打开一个新的终端&#xff1a; gdb-mult…

Selenium教程11:模拟账号密码,自动登入qq空间

Python爬虫教程30&#xff1a;Selenium网页元素&#xff0c;定位的8种方法&#xff01; Selenium自动化教程02&#xff1a;浏览器options配置及常用的操作方法 Selenium自动化教程03&#xff1a;延时等待的3种方式 Selenium自动化教程04&#xff1a;鼠标键盘网页的模拟操作 …

文件的相关概念及用法

文件的作用 程序运行时产生的数据都属于临时文件&#xff0c;程序一旦运行结束就会被释放。若想让数据保存下来&#xff0c;则可以通过文件将数据持久化 文件需要包含的头文件<fstream>(文件流) 文件分类 文件分为文本文件和二进制文件。 文本文件&#xff1a;文件以…

快速上手Git

目录 一、Git概述 二、Git的常用命令 Git全局配置 获取Git仓库 基本概念 本地仓库操作 远程仓库操作 分支操作 标签操作 三、在IDEA中使用Git 在IDEA中配置Git 本地仓库操作 远程仓库操作 分支操作 冲突解决 一、Git概述 Git是一个分布式版本控制工具&…

探索设计模式的魅力:深入了解适配器模式-优雅地解决接口不匹配问题

设计模式专栏&#xff1a;http://t.csdnimg.cn/nolNS 目录 一、引言 1. 概述 2. 为什么需要适配器模式 3. 本文的目的和结构 二、简价 1. 适配器模式的定义和特点 定义 特点 2. 适配器模式的作用和适用场景 作用 适用场景 3. 适配器模式与其他设计模式的比较 三、适配…

DolphinScheduler + Amazon EMR Serverless 的集成实践

01 背景 Apache DolphinScheduler 是一个分布式的可视化 DAG 工作流任务调度开源系统&#xff0c;具有简单易用、高可靠、高扩展性、⽀持丰富的使用场景、提供多租户模式等特性。适用于企业级场景&#xff0c;提供了一个可视化操作任务、工作流和全生命周期数据处理过程的解决方…

代码随想录算法刷题训练营day18

代码随想录算法刷题训练营day18&#xff1a;LeetCode(257)二叉树的所有路径、LeetCode(404)左叶子之和 LeetCode(257)二叉树的所有路径 题目 代码 import java.util.ArrayList; import java.util.List;/*** Definition for a binary tree node.* public class TreeNode {* …

媒体邀约:怎么吸引总体目标受众?

新闻媒体影响力日益扩大。不论是公司、机构还是其他&#xff0c;都希望能够通过新闻媒体的曝光来吸引更多总体目标受众。要想真正吸引住总体目标受众并非易事&#xff0c;需要一定的方案和方法。下面我们就深入探究媒体邀约推广的真相&#xff0c;共享怎么吸引总体目标受众的方…