c++内存管理_复习

  • new与placement new
    • new:

      • 先调用operator new(大小),而operator new()会调用malloc尝试分配内存,失败则调用_callnewh()来释放内存,直至分配成功
        • 可以设置分配失败的处理函数:将写好的处理函数作为参数传入set_new_handler即可
      • 然后将得到的指针转型
      • 最后通过指针调用构造函数
    • placement new
      placementnew

      • 先调用operator new(大小, address),该带2个参数的函数直接返回buf,不做任何改动,即不分配内存。
      • 然后将得到的指针转型
      • 最后通过指针调用构造函数

总结:new会分配内存后调用构造函数,而placement new相当于只是调用构造函数。因此我们可以像下面这样模拟new的行为:
模拟new和delete

  • 容器的内存分配方式
    当元素放入容器时,容器也需要为其分配一块空间,但其不是用的new和delete,而是将其包装在construct()和destroy()函数中

  • 设计一个内存池

    • 重载局部的operator new()
      • 方法1:单独多使用一些指针来将空闲块连成链表
        下面在节点中使用next指针来将小块链接起来

        void* A::operator new(size_t size)
        {cout << "局部new" << endl;A* p;if (!A::freeStore){//申请一大块空间//A::freeStore = (A*)malloc(size * Chunk);A::freeStore = reinterpret_cast<A*>(new char[Chunk*size]);p = A::freeStore;//初始化p指针也指向头节点//串成链表for (int i = 0; i < Chunk; i++){p->next = p + 1;//地址增大4,就是一个A的大小p = p->next;}p->next = NULL;}//把链表头部的空闲块拿出来用p = A::freeStore;A::freeStore = A::freeStore->next;return p;
        }
        
      • 使用嵌入式指针:也就是指针临时借用一下空闲块里的空间,等到需要分配出去使用时就正常使用即可。
        下面的rep和next占用同一片空间

        class A
        {
        private://数据struct Airplane//占8字节{int miles;char type;};
        private:union{Airplane rep;A* next;};static A* freeStore;//指向链表的头部的指针static const int Chunk = 3;//内存池容纳几个
        public:static void* operator new(size_t size);static void operator delete(void* ptr);void set(int m, char t)....void show()....
        };
        
    • 重载局部的operator delete()
      • 采用头插法,将空闲块插入到链表头
        void A::operator delete(void* ptr)
        {cout << "局部delete" << endl;//头插法static_cast<A*>(ptr)->next = A::freeStore;A::freeStore = static_cast<A*>(ptr);
        }
        
    • c语言版本的内存池
      • 先写个宏定义
        #define malloc(mp, size) _malloc(mp, size)
        #define free(mp, ptr) _free(mp, ptr)
        
      • 定义一个大的内存块,这里称其为页
        typedef struct mempool_s
        {int block_size;//一小块的大小int free_count;//该页内剩余空闲块的个数void *mem;//指向该页首地址void *ptr;//指向该页中最新创建的块的地址(即下次要分配出去内存的块)
        } mempool_t;
        
      • 写一个内存池初始化函数,将128个小块串成链表
        int memp_init(mempool_t *mp, size_t block_size)
        {printf("block_size: %ld\n", block_size);if (!mp) return -1;memset(mp, 0, sizeof(mempool_t));mp->block_size = block_size;mp->free_count = MEM_PAGE_SIZE / block_size;mp->mem = malloc(MEM_PAGE_SIZE);if(!mp->mem) return -1;mp->ptr = mp->mem;//把该页中的128块串成链表char *ptr = mp->ptr;//ptr指针指向第1块for (int i = 0; i < mp->free_count; i++){//使用2级指针:一级指针ptr,(char**)ptr将其强转为指向char*的指针,//*(char**)ptr为其指向的char*地址,将该地址赋值为ptr所指块的下一块地址*(char**)ptr = ptr + block_size;ptr += block_size;}*(char**)ptr = NULL;//最后一块的前几个字节保存的是NULLreturn 0;
        }
        
    • 最后写内存分配与释放的函数即可。释放时同样使用头插法

- G2.9 alloc的大致流程:page8

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

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

相关文章

Vue3 使用 Vue Router 时,params 传参失效

前言&#xff1a; 在写项目的时候&#xff0c;使用了 vue-router 的 params 进行传参&#xff0c;但是在详情页面中一直获取不到参数。原因&#xff1a;Vue Router 在2022-8-22的那次更新后&#xff0c;使用这种方式在新页面上无法获取&#xff01; 正文&#xff1a; 在列表页进…

deeplabcut

import pandas as pd import h5py import pickle import json import os # 读取 CSV 文件 csv_file_path /mnt/data/CollectedData_dlc.csv csv_data pd.read_csv(csv_file_path) # 读取 H5 文件 h5_file_path /mnt/data/CollectedData_dlc.h5 with h5py.File(h5_file_pat…

LeetCode题练习与总结:只出现一次的数字Ⅱ--137

一、题目描述 给你一个整数数组 nums &#xff0c;除某个元素仅出现 一次 外&#xff0c;其余每个元素都恰出现 三次 。请你找出并返回那个只出现了一次的元素。 你必须设计并实现线性时间复杂度的算法且使用常数级空间来解决此问题。 示例 1&#xff1a; 输入&#xff1a;n…

K8S日常运维手册

Kubernetes&#xff08;简称 K8S&#xff09;是一种广泛使用的容器编排平台&#xff0c;能够自动化部署、扩展和管理容器化应用。对于运维人员来说&#xff0c;掌握 Kubernetes 的日常运维技能是确保系统稳定运行的关键。本文将介绍一些 Kubernetes 日常运维的基本操作与技巧&a…

虚拟机装入kali linux

VMware 首先需要先安装VMware Workstation Pro可以根据这篇文章来下载VMware 下载kali linux Installer Images VS Virtual Machines Installer Images&#xff08;安装镜像&#xff09;Virtual Machines&#xff08;虚拟机&#xff09; 直接访问硬件&#xff0c;定制内核…

Matlab|【防骗帖】考虑时空相关性的风电功率预测误差建模与分析

目录 1 主要内容 2 部分程序 3 下载链接 1 主要内容 这个程序《考虑时空相关性的风电功率预测误差建模与分析》画的图片非常漂亮&#xff0c;和原文献基本一致&#xff0c;但是实际上内容并未实现出来&#xff0c;主要就是利用现有的风电预测的数据和结果做了相关的图&#…

【数据结构】(C语言):链表

链表&#xff1a; 基本单位是节点。节点至少两部分&#xff1a;数据&#xff0c;下一个数据的地址。头指针head&#xff0c;始终指向链表的第一个节点。若没有节点&#xff0c;则headNULL。链表在内存中是非连续的。不能使用索引&#xff08;下标&#xff09;查找元素。只能从…

解决:Xshell通过SSH协议连接Ubuntu服务器报“服务器发送了一个意外的数据包,received:3,expected:20”

下图所示&#xff1a; 日志也基本看不出来问题在哪&#xff0c;只是说断开了连接大概是验证失败。有幸在某论坛评论区找到了原因&#xff0c;是因为我的xshell版本太低了而服务器的ssh版本太高&#xff0c;高版本的ssh默认屏蔽了一部分不太安全的算法导致建立连接的时候验证失败…

C++ 14新特性个人总结

variable templates 变量模板。这个特性允许模板被用于定义变量&#xff0c;就像之前模板可以用于定义函数或类型一样。变量模板为模板编程带来了新的灵活性&#xff0c;特别是在定义泛化的常量和元编程时非常有用。 变量模板的基本语法 变量模板的声明遵循以下基本语法&am…

解决Vue+Vite打包后Leaflet的marker图标不显示的问题

前言 用Leaflet写关于WebGIS的开发&#xff0c;用Vite或者webpack打包&#xff0c;打包后会找不到图标&#xff0c;如下所示。 直言的说&#xff0c;笔者去网上搜了搜&#xff0c;其实收到一个比较好是答案。网址如下。 &#xff08;完美解决~&#xff09;关于VueLeaflet添加…

eslint 与 prettier 的一些常见的配置项(很详细)

目录 1、eslint 常见配置项&#xff08;语法规范&#xff09; 2、 prettier 常见的配置项&#xff08;格式规范&#xff09; 代码规范相关内容看小编的该文章&#xff0c;获取对你有更好的帮助 vsCode代码格式化&#xff08;理解eslint、vetur、prettier&#xff0c;实现格式…

IDEA启动报错:Abnormal build process termination...

一、问题描述 因为项目需要&#xff0c;同时打开了两个idea&#xff0c;突然发现一个启动的时候报错&#xff0c;有点莫名其妙&#xff0c;刚还好好的&#xff0c;为啥就不能用了&#xff0c;一顿百度找方法&#xff0c;试了各种方法&#xff0c;像重新安装jdk、重启系统发现都…

TensorFlow开源项目

欢迎来到 Papicatch的博客 文章目录 &#x1f349;TensorFlow介绍 &#x1f349;主要特点和功能 &#x1f348;多语言支持 &#x1f348;灵活的架构 &#x1f348;分布式训练 &#x1f348;跨平台部署 &#x1f348;强大的工具链 &#x1f348;丰富的社区和生态系统 &a…

c++基本数据类型和计算(一)习题讲解

1.【单选题】以下说法正确的是? A. unsigned 类型的值 最大为0xFFFFFFFF B. float类型的值大约有15位精度 C.bool类型占用4个字节 解析&#xff1a; 选项A&#xff1a;unsigned 类型的值 最大为 4个字节&#xff0c;正确。选项B&#xff1a; 因为float类型的值是单精度的浮…

Vue3基础使用

目录 一、创建Vue3工程 (一)、cli (二)、vite 二、常用Composition API (一)、setup函数 (二)、ref函数 (三)、reactive函数 (四)、setup注意事项 (五)、计算属性 (六)、watch (七)、watchEffect函数 (八)、生命周期 1、以配置项的形式使用生命周期钩子 2、组合式…

kafka-简单代码实现生产者消费者

生产者代码&#xff1a; package com.kafka.test;import org.apache.kafka.clients.producer.KafkaProducer; import org.apache.kafka.clients.producer.ProducerConfig; import org.apache.kafka.clients.producer.ProducerRecord; import org.apache.kafka.common.seriali…

【机器学习-10】 | Scikit-Learn工具包进阶指南:Scikit-Learn工具包之支持向量机模块研究

&#x1f3a9; 欢迎来到技术探索的奇幻世界&#x1f468;‍&#x1f4bb; &#x1f4dc; 个人主页&#xff1a;一伦明悦-CSDN博客 ✍&#x1f3fb; 作者简介&#xff1a; C软件开发、Python机器学习爱好者 &#x1f5e3;️ 互动与支持&#xff1a;&#x1f4ac;评论 &…

高考填报志愿攻略,5个步骤选专业和院校

在高考完毕出成绩的时候&#xff0c;很多人会陷入迷茫中&#xff0c;好像努力了这么多年&#xff0c;却不知道怎么规划好未来。怎么填报志愿合适&#xff1f;在填报志愿方面有几个内容需要弄清楚&#xff0c;按部就班就能找到方向&#xff0c;一起来了解一下正确的步骤吧。 第…

入局AI手机 苹果公布Apple Intelligence

日前&#xff0c;苹果WWDC 2024如期召开。在这持续1个小时44分钟的开发者大会上&#xff0c;苹果在前一个小时里更新了iOS、iPadOS、MacOS等操作系统&#xff0c;而且还首次更新了visionOS。余下的时间全部留给了苹果的“AI大礼包”——Apple Intelligence&#xff08;苹果智能…

请说明Thread类中run和start的区别,从方法的区别,及运行结果的区别分别说明

方法本身的区别 start() 方法&#xff1a; run()方法是Thread类的一个普通方法&#xff0c;它包含了线程要执行的代码。当你直接调用一个线程的run()方法&#xff08;如myThread.run()&#xff09;&#xff0c;你实际上是在当前线程&#xff08;通常是主线程&#xff09;中执行…