C++内存分配策略

news2024/11/15 15:44:26

目录

基础概念

内存布局

分配方式

实现

1.new和delete

2.利用空间配置器alloc

3.用malloc和free

4.静态内存分配


基础概念

在讲内存分配之前,先对一些基础概念进行阐述,以便能更好的讨论问题

内存布局

代码编译为可执行程序后运行占用的内存可以分为以下几个区域:

1.栈区(stack) :  由编译器自动分配释放,用于存放函数的参数值,局部变量的值等;在一个进程中,位于用户虚拟地址空间顶部的是用户栈,编译器用它来实现函数的调用;栈上的内存在函数返回时就会自动释放;栈区的内存地址延伸方式从高地址向地址;栈内存的大小通常是有限的,所以大量使用可能导致栈溢出。
2.堆区(heap) : 一般由程序员分配释放,若程序员不释放,程序结束时可能由OS(操作系统)回收;堆可以动态地扩展和收缩,注意它与数据结构中的堆是两回事,分配方式倒是类似于链表。
3.全局区(静态区、static): 全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。程序结束后由系统释放。
4.文字常量区 : 常量字符串就是放在这里的,程序结束后由系统释放。
5. 程序代码区 : 存放函数体的二进制代码,代码里面的全局函数和类成员函数编译后就是存在这个区域。

一个可执行程序,在不运行时占用磁盘空间的是全局区、文字常量区和程序代码区,运行后栈区和堆区在内存里面才划分出来工作。下面是区域划分图:

实例分析

int  g_a=0;   //全局初始化区 

static int g_b = 0; //全局变量,static限制了使用区域

char *g_p1;   //全局未初始化区    

static void func(int x, int y) //x,y是形参,栈区
{
    static int x1 =0;//局部(静态)初始化区   
    int x2 = 0;  //局部变量,栈区 
}

int  main()    
{    
  int  x; //局部变量,存放在栈区   
  char  s[]="abc"; //局部变量,栈    
  char  *p1; //局部变量,栈    
  char  *p2="abcdef"; //"abcdef/0"在常量区,p3在栈上。    
   
  p1 =  (char  *)malloc(23);  //分配得来得23和25字节的区域就在堆区 
  strcpy(p1,"abcdef"); //"abcdef\0"放在常量区,编译器可能会将它与p2所指向的"abcdef"  优化成一个地方

  int* p4 = new int(2);  //p4是局部变量,存放在栈区,p4指向的内存是堆区
}    

分配方式

C/C++内存分配方式有3种:

1.从静态存储区域分配:  是在程序编译和链接时就确定好的内存;这些内存在程序整个运行期间都存在,如全局变量,static变量等。
2.在栈上创建:在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放,栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限,如数组,局部变量,形参。 
3.从堆上分配:亦称动态内存分配 ,是在程序加载、调入、执行的时候分配/回收的内存;程序在运行的时候用 malloc 或 new 申请任意多少的内存,程序员自己负责在何时用 free 或 delete 释放内存。动态内存的生存期由程序员决定 ,使用非常灵活,但如果在堆上分配了空间,就有责任回收它,否则运行的程序会出现内存泄漏,频繁地分配和释放不同大小的堆空间将会产生堆内碎块。

实现

1.new和delete

在C++里面这种方式是用的最多的,代码如下:

    template <class T> 
    struct CreateUsingNew
    {
        template <typename... Args>
        static T* Create(Args&&... args)
        { return new T(std::forward<Args>(args)...); }
        
        static void Destroy(T* p)
        { delete p; }
    };

2.利用空间配置器alloc

在STL中空间配置器的4个函数:

内存的配置:alloc::allocate();
对象的构造:alloc::construct();
对象的析构:alloc::destroy();
内存的释放:alloc::deallocate();

 利用空间分配器分配内存的代码如下:

    template<template<class> class Alloc>
    struct CreateUsing
    {
        template <class T>
        struct Allocator
        {
            static Alloc<T> allocator;

            template <typename... Args>
            static T* Create(Args&&... args)
            {
                return new (allocator.allocate(1)) T(std::forward<Args>(args)...);
            }

            static void Destroy(T* p)
            {
                //allocator.destroy(p);
                p->~T();
                allocator.deallocate(p,1);
            }
        };
    };

STL中容器默认空间分配器为std::allocator<_Tp>,内存分配和释放的接口allocate和deallocate内部实现只是将::operator new和::operator delete进行封装,没用做特殊处理;如果还想深入了解STL的空间配置器的相关内容,可以查阅我的博客深入理解STL空间分配器(一)-CSDN博客、深入理解STL空间分配器(二)-CSDN博客、深入理解STL空间分配器(三)-CSDN博客、深入理解STL空间分配器(四)-CSDN博客。

3.用malloc和free

 C语言的传统方式分配和释放内存,代码如下:

    template <class T> 
    struct CreateUsingMalloc
    {
        template <typename... Args>
        static T* Create(Args&&... args)
        {
            void* p = std::malloc(sizeof(T));
            if (!p) return 0;
            return new(p) T(std::forward<Args>(args)...);
        }
        
        static void Destroy(T* p)
        {
            p->~T();
            std::free(p);
        }
    };

4.静态内存分配

代码如下:

    template <class T> 
    struct CreateStatic
    {
        
#ifdef _MSC_VER
#pragma warning( push ) 
#pragma warning( disable : 4121 )
// alignment of a member was sensitive to packing
#endif // _MSC_VER

        union MaxAlign
        {
            char t_[sizeof(T)];
            short int shortInt_;
            int int_;
            long int longInt_;
            float float_;
            double double_;
            long double longDouble_;
            struct Test;
            int Test::* pMember_;
            int (Test::*pMemberFn_)(int);
        };
        
#ifdef _MSC_VER
#pragma warning( pop )
#endif // _MSC_VER
        
        template <typename... Args>
        static T* Create(Args&&... args)
        {
            static MaxAlign staticMemory_;
            return new(&staticMemory_) T(std::forward<Args>(args)...);
        }
        
        static void Destroy(T* p)
        {
            p->~T();
        }
    };

上面的例子都用到了std::forward,实现了构造函数参数的完美转发,它的用法可以参考博客C++之std::forward-CSDN博客

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

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

相关文章

【现代密码学】笔记5--伪随机置换(分组加密)《introduction to modern cryphtography》

【现代密码学】笔记5--伪随机置换&#xff08;分组加密&#xff09;《introduction to modern cryphtography》 写在最前面5 伪随机排列实践构造&#xff08;块密码/分组密码&#xff09; 写在最前面 主要在 哈工大密码学课程 张宇老师课件 的基础上学习记录笔记。 内容补充&…

云服务器部署Stable Diffusion Webui从0到1总结:反复重启+循环debug

文章目录 在学校服务器部署Stable Diffusion Webui&#xff08;一&#xff09;准备工作&#xff08;二&#xff09;环境配置&#xff08;三&#xff09;git拉取项目到本地&#xff08;四&#xff09;运行项目 遇到的问题&#xff1a;&#xff08;一&#xff09;使用git clone时…

jmeter--6.跨线程组关联

目录 1. 跨线程组实现接口关联 2. 跨线程组实现Cookie关联 1. 跨线程组实现接口关联 1.1 根据json/正则的方式提取到需要的响应数据 1.2 在接口下新增一个BeanShell 后置处理器&#xff0c;并通过函数助手写入【${__setProperty(new_token,${access_token},)}】&#xff0c;…

基于Java (spring-boot)的社团管理系统

一、项目介绍 系统管理员的功能概述&#xff1a; ①用户管理 a.注册用户账户 当一个新用户注册时&#xff0c;用户填写基本信息并上传。用户基本信息包括账号、 姓名、密码、手机、地址等信息。 b.用户信息管理 管理员可以查看系统所有用户的基本信息&#xff0c;并修改和…

10分钟快速上手LLM大模型Python前端开发(三)之显示模块(一)

10分钟快速上手LLM大模型Python前端开发&#xff08;三&#xff09;之显示模块&#xff08;一&#xff09; 显示代码初步测试 通用显示方法显示字符串显示dataframe显示Markdown 微信公众号&#xff1a;leetcode_algos_life&#xff0c;代码随想随记 小红书&#xff1a;4124081…

基于Java (spring-boot)的停车场管理系统

一、项目介绍 基于Java (spring-boot)的停车场管理系统、预订车位系统、停车缴费系统功能&#xff1a; 登录、注册、后台首页、用户信息管理、车辆信息管理、新增车辆、车位费用设置、停泊车辆查询、车辆进出管理、登录日志查询、个人中心、预定停车位、缴费信息。 适用人群&…

jmeter--5.断言

目录 1. 响应断言 1.1 添加断言 1.2 名词解释 断言失败显示示例 2. json断言 2.1 添加断言 2.2 名词解释 断言失败显示示例 2.3 json断言应用 3. beanshell断言 3.1 添加断言 3.2 原理 断言失败显示示例 1. 响应断言 1.1 添加断言 线程组->添加->断言->…

202406读书笔记|《沉睡的线条世界》——翻山越岭,只为与你分享点滴的快乐

《沉睡的线条世界》登登登Dn绘著&#xff0c;简简单单的小画&#xff0c;简简单单的线条&#xff0c;简简单单的语言&#xff0c;温馨又有一点暖心。 怎样的你都好&#xff0c;做最真实的自己。 部分节选如下&#xff1a; 愿你我永远有热情&#xff0c;永远能为生活的每一个小惊…

运筹说 第67期 | 动态规划模型的建立与求解

通过前一期的学习&#xff0c;我们已经学会了动态规划的基本概念和基本原理。本期小编带大家学习动态规划模型的建立与求解。 动态规划模型的建立 一 概述 建立动态规划的模型&#xff0c;就是分析问题并建立问题的动态规划基本方程。 成功地应用动态规划方法的关键&#x…

[渗透测试学习] Hospital - HackTheBox

文章目录 信息搜集getshell提权信息搜集 nmap扫描一下端口 发现8080端口和443端口有http服务 然后发现3389端口是启用了ms-wbt-server服务 在对443端口的扫描没有收获,并且只有邮箱登录界面无法注册 接着看向8080端口,我们随便注册用户登录后发现有文件上传功能 getshell …

Linux入门级常用命令学习笔记

以下命令是我跟着编程界的大佬鱼皮学习Linux时用的命令&#xff0c;我把它都记下来&#xff0c;权当作笔记&#xff0c;可供自己后期反复练习使用&#xff0c;让我们学习一下最基本的Linux命令吧。 一、Linux实战命令 在dos下 【ssh 服务器ip】可以连接服务器&#xff0c;输入…

HCIA基础知识

IP地址、静态路由、动态路由、交换机 OSPF RIP DHCP VLAN ACL NAT OSI TCP/IP UDP TCP 三次握手&#xff0c;四次挥手&#xff0c;报头 什么是网络&#xff1f; 由网络连接设备通过传输介质将网络终端设备连接起来&#xff0c;进行资源共享、信息传递的平台。 OSI七…

运筹说 第98期|无约束极值问题

上一期我们一起学习了关于非线性规划问题的一维搜索方法的相关内容&#xff0c;本期小编将带大家学习非线性规划的无约束极值问题。 下面&#xff0c;让我们从实际问题出发&#xff0c;学习无约束极值问题吧&#xff01; 一、问题描述及求解原理 1 无约束极值问题的定义 无约…

【C++干货铺】会旋转的二叉树——AVLTree

个人主页点击直达&#xff1a;小白不是程序媛 C系列专栏&#xff1a;C干货铺 代码仓库&#xff1a;Gitee 目录 前言 AVL树 AVL树的概念 AVL树结点的定义 AVL树的插入 寻找插入结点的位置 修改平衡因子 AVL树的旋转 右单旋 左单旋 先右旋再左旋 先左旋再右旋 AVL树…

【JAVA-打包jar】jar不能双击运行,Jar包找不到主类

我的问题比较简单&#xff0c;搞了一下午&#xff0c;查阅了很多教程&#xff0c;无意发现&#xff0c;居然是 jdk过期需要更新&#xff01; 气的吐血&#xff01; 所以不要废话&#xff0c;首先检查自己的环境变量和JDK&#xff01;&#xff01;&#xff01; 环境变量&…

ML:2-1-4理解python如何实现forward prop

文章目录 1. 单层上的向前传播forward prop2. 前向传播的一般实现3. 通用人工智能 1. 单层上的向前传播forward prop 【了解在python中如何实现forward prop】 继续使用咖啡烘焙模型&#xff1a; 了解经过每一个神经元的预测过程。设置每一个神经元的w&#xff0c;b值。从而得…

(2024,分数蒸馏抽样,Delta 降噪分数,LoRA)PALP:文本到图像模型的提示对齐个性化

PALP: Prompt Aligned Personalization of Text-to-Image Models 公和众和号&#xff1a;EDPJ&#xff08;进 Q 交流群&#xff1a;922230617 或加 VX&#xff1a;CV_EDPJ 进 V 交流群&#xff09; 目录 0. 摘要 4. 提示对齐方法 4.1 概述 4.2 个性化 4.3 提示对齐分数抽…

深度学习记录--Train/dev/test sets

为什么需要训练集、验证集(简单交叉验证集)和测试集&#xff1f; 为了创建高效的神经网络&#xff0c;需要不断进行训练(迭代) 一个神经网络的产生 从最开始的想法idea开始&#xff0c;然后付诸于代码code&#xff0c;根据结果验证反过来对一开始的想法idea进行修正&#xf…

架构简介,到底什么是架构?

1. 前言 对技术人员来说&#xff0c;“架构”是一个再常见不过的词儿了。我们经常对新员工培训整个系统的架构&#xff0c;参加架构设计评审&#xff0c;学习业界开源系统&#xff08;例如&#xff0c;MySQL、Hadoop&#xff09;的架构&#xff0c;研究大公司的架构实现&#…

2024年腾讯云服务器多少钱1个月?

2024年腾讯云服务器多少钱1个月&#xff1f;5元一个月&#xff0c;62元一年&#xff0c;更多腾讯云服务器精准报价。腾讯云服务器租用优惠价格表&#xff1a;轻量应用服务器2核2G3M价格62元一年、2核2G4M价格118元一年&#xff0c;540元三年、2核4G5M带宽218元一年&#xff0c;…