摘要:“new”是C++的一个关键字,同时也是操作符。关于new的话题非常多,因为它确实比较复杂,也非常神秘。

本文分享自华为云社区《如何编写高效、优雅、可信代码系列(2)——你真的会用new吗》,原文作者:我是一颗大西瓜 。

C++内存管理

1. C++内存分配

C++中的程序加载到内存后按照代码区、数据区、堆区、栈区进行布局,其中数据区又可以分为自由存储区、全局/静态存储区和常量存储区,各区所长如下:

  • 栈区
    函数执行的时候,局部变量的存储单元都在栈上创建,函数执行结束后存储单元会自动释放。栈内存分配运算内置于处理器指令集中,效率高,但分配内存容量有限。
  • 堆区
    堆就是new出来的内存块,编译器不管释放,由应用程序控制,new对应delete。如果没释放掉,程序结束后,操作系统会自动回收。
  • 自由存储区
    C中malloc分配的内存块。用free结束生命周期。
  • 全局/静态存储区
    全局变量和静态变量被分配到同一块内存中,定义的时候就会初始化。
  • 常量存储区
    比较特殊的存储区,存放常量,不允许修改。

堆和栈的区别

  • 管理方式
    栈由编译器自动管理,堆由程序员控制
  • 空间大小
    32位系统下,堆内存可以达到4GB,栈有一定的空间大小
  • 碎片管理
    对于堆,频繁的new/delete肯定造成内存空间的不连续,产生大量内存碎片降低程序效率;栈由于遵循先进后出的规则,不会产生空隙
  • 生长方向
    堆是向上生长的,即向着内存地址增加的方向增长;而栈是向着内存地址减小的方向增长的
  • 分配方式
    堆是动态分配的,栈有动态分配和静态分配之分:静态分配由编译器完成,动态分配由alloca函数完成,即使是动态分配,依然是编译器自动释放
  • 分配效率
    计算机底层提供了栈的支持,分配了专门的寄存器存放栈的地址,压栈出栈都有专门的指令执行,这决定了栈的效率会比较高。堆则是由C/C++函数库提供的,机制比较复杂,比如为了分配某个大小的内存需要在堆内存中搜索可用足够大小的空间,效率比栈要低的多

2. new/delete和new []/delete []

  • 回收new分配的单个对象内存空间时用delete,回收用new[]分配的一组对象时用delete[]
  • 对于内置类型(int/double/float/char/…),由于new[]申请内存时,编译器还会悄悄在内存中保存整数,表示指针数组的个数,所以delete/delete[]都可以正确释放所申请的内存空间
  • 建议在调用new时使用的[],那么调用delete也使用[]

3. new的三种形态

  • new operator 常用的new,语言函数内建,不能重载。调用过程中实际完成的有三件事:
  1. 为类型对象分配内存;
  2. 调用构造函数初始化内存对象;
  3. 返回对象指针
    如果是在堆上建立对象,直接使用new operator。
  • operator new 普通操作符,可以重载。如果仅仅是分配内存,那么应该调用operator new,但不负责初始化。系统默认提供的分配器在时间和空间两方面都存在一些问题:分配器速度较慢,分配小型对象时空间浪费严重,重载new/delete有三方面好处:
  1. 改善效率
  2. 检测代码中的内存错误
  3. 获得内存使用的统计数据
  4. C++标准规定,重载的operator new必须是类成员函数或全局函数,全局的operator new重载不应该改变原有签名,而是直接无缝替换原有版本。全局重载很有侵略性,别人使用你的库无法使用默认的new,而具体类的重载只会影响本class和其派生类,但是类的operator new函数重载必须声明为static,因为operator new是在类的具体对象被构建出来之前调用的。
  5. 为了获得2和3的优势,重载的operator new需要如下函数声明void* operator new(size_t, const char* file, int line);
  • placement new 定义在库<<new>>中。如果想在一块已经获得内存里建立对象,那么应该调用placement new。通常情况不建议使用,但在某些对时间要求非常高的应用中可以考虑,因为选择合适的构造函数完成对象初始化是一个时间相对较长的过程。

点击关注,第一时间了解华为云新鲜技术~

在C++中,你真的会用new吗?的更多相关文章

  1. 在React中你真的用对了Ajax吗?

    通过AJAX加载初始数据 通过AJAX加载数据是一个很普遍的场景.在React组件中如何通过AJAX请求来加载数据呢?首先,AJAX请求的源URL应该通过props传入:其次,最好在component ...

  2. 项目开发中,真的有必要定义VO,BO,PO,DO,DTO这些吗?

    存在即是合理的,业务复杂,人员协同性要求高的场景下,这些规范性的东西不按着来虽然不会出错,程序照样跑,但是遵守规范会让程序更具扩展性和可读性,都是前辈血淋淋的宝贵经验,为什么不用? 随着现在后端编程标 ...

  3. TypeScript 中的 "=>" 真的很好用!!!

    class funs { public $scope: IBarPadScope; constructor($scope: IBarPadScope) { this.$scope = $scope; ...

  4. Java中Set真的是无序的吗?

    我们经常听说List是有序且可重复的,Set是无序且不重复的.这是一个误区,这里所说的顺序有两个概念,一是按照添加的顺序排列,二是按,照自然顺序a-z排列.Set并不是无序的传统所说的Set无序指的是 ...

  5. Fastreport使用经验(转)在Delphi程序中访问报表对象

    Fastreport使用经验(转) 在Delphi程序中访问报表对象 最基本的方法就是frxReport1.FindObject. 然后把返回的对象强制转换成它的类型,当然,在报表中必须真的有这么个东 ...

  6. 谈谈如何在面试中发掘程序猿的核心竞争力zz

    早两天看了知乎日报的这篇文章<什么是程序员的核心竞争力?>,caoz讲的几点是让我感同身受.这让我联想起了给程序猿的面试,其实也就是通过短暂的接触来发掘程序猿的核心竞争力.接下来我就谈谈我 ...

  7. 纪中集训 Day1

    今天早上起来吃饭,发现纪中伙食真的是太差了!!!什么都不热,早餐的面包还好,然后就迎来了美好的早晨= = 早上做一套题,T1T2果断秒,T3一看就是noi原题,还好看过题解会写,然后就愉快的码+Deb ...

  8. java.lang.Class类中的某些方法

    反射的代码会经常遇到,Class类中方法真的多,且用的少,大多用在底层源码这块,既然看到了,就记录一下吧,说不定以后厉害了,自己封装框架,haha getComponentType()方法: Syst ...

  9. MVP架构在xamarin android中的简单使用

    好几个月没写文章了,使用xamarin android也快接近两年,还有一个月职业生涯就到两个年了,从刚出来啥也不会了,到现在回头看这个项目,真jb操蛋(真辛苦了实施的人了,无数次吐槽怎么这么丑),怪 ...

  10. go中的map[Interface{}]Interface{}理解

    map里面的k,v支持很多的类型.对于go来说也是,go中有个接口的概念,任何对象都实现了一个空接口.那么我们把map里面的k,v都用interface去定义,当我们在使用这个map的时候,我们可以把 ...

随机推荐

  1. MyBatis进阶--接口代理方式实现Dao 和动态SQL

    MyBatis接口代理方式实现Dao层 接口代理方式-实现规则 传统方式实现Dao层,我们既要写接口.还要写实现类.而MyBatis框架可以帮助我们省略写Dao层接口实现类的步骤.程序员只需要编写接口 ...

  2. .Net 中的 string、String、StringBuffer 内存处理性能 和 应用场景

    body { font-family: Segoe UI, SegoeUI, Helvetica Neue, Helvetica, Arial, sans-serif } code { color: ...

  3. [bug] Hive启动报错:hive Name node is in safe mode.

    关闭HDFS安全模式 hadoop dfsadmin -safemode leave

  4. linux服务器默认使用中文字符集zh_CN.UTF-8

    linux服务器默认使用中文字符集zh_CN.UTF-8 一.问题描述和相关概念 linux服务器的字符集设置可能影响到网站页面出现 "???" 等问号乱码,还有可能导致文件中的汉 ...

  5. MyBatis 动态 SQL 语句中出现 '<' 的问题

    问题描述 映射接口方法如下: /** * 根据姓名和年龄查询用户信息 * @param name 姓名 * @param user 获取年龄 * @return */ public List<U ...

  6. mybatis 同时使用 XML 和注解

    引言 学过 MyBatis 框架的童靴都知道, MyBatis 支持 XML 和注解两种方式配置,如下: 使用 XML 方式配置 只写明 XML 的 resource 路径(或者URL路径) < ...

  7. Linux(CentOS 7) 安全加固之非业务端口服务关闭 postfix port 25

    目录 关闭TCP 25 端口对应的服务 1. 确认对应端口的进程 2. 查找与关闭对应服务 3. 确认结果,端口已关闭 关闭TCP 25 端口对应的服务 [0 root@Qvps /root] #ca ...

  8. [论文阅读笔记] Are Meta-Paths Necessary, Revisiting Heterogeneous Graph Embeddings

    [论文阅读笔记] Are Meta-Paths Necessary? Revisiting Heterogeneous Graph Embeddings 本文结构 解决问题 主要贡献 算法原理 参考文 ...

  9. 微信小程序在ios系统不兼容new Date('yyyy-mm-dd')

    微信小程序中使用new Date('2021-04-01 10:11:20')来转换时间在苹果手机不生效 兼容写法为new Date('2021/04/01 10:11:20')

  10. 实用程序包utils - 基于Rollup打包输出各模块文件(二)

    上一次,我们讲到了如何去搭建一个前端工具库的工程,那么今天我们来聊一聊如何去将其打包输出. 需求 事情是这个样子的.我有一个这样的需求,或者是我发现有这么一个需求.就是有时候吧,我也不想搞的那么复杂, ...