C++内存管理知识总结<一 >——<内存部件介绍及使用>

 在讲内存之前,咱先说一下内存分配方式,下面百度了两张图:

  

具体详细介绍我就不说了,网上很多,接下来进行咱们得主题,本章主要介绍C++语言本身为我们提供的内存相关的使用工具

前言

  首先我们先说一下什么是内存管理,内存管理都要干什么,内存管理用的就是内存池的概念来管理内存,就干两件事,一个是节省空间(new一块内存头和尾都附带一个cookies占8个字节)另一个是提升分配速度,现在我们用的STL很方便,我们从来不用关心内存的分配,其实STL里面有一个allocator,是它帮我们进行了内存管理。

一、C++ memory primitives

  C++ 应用程序使用内存的途径方式如下:

 当然我们不推荐直接使用最底层O.S.API(操作系统的内存调用API)的函数,因为越低阶的函数跟操作系统的绑定就越密切,程序移植性就会越低,所以几乎没人直接使用这么低阶的函数,我们所探讨的只是CRT这一层之上的工具情况,基础工具比较如下:

 

1、new/delete背后的故事

  new的背后一般有如下3步,分配空间、类型转换、调用构造函数,如下所示:

  delete背后经历了调用析构函数、释放内存的动作

注意:不能直接调用构造函数(除了new里面之外),但是可以调用析构函数

2、array new/array delete背后的故事 

  对数组的操作我们需要中括号[]以告诉编译器我们现在要new一个数组,所以这个中括号相当于一个标识一样,同样,delete的时候,我们也要加上中括号[],同样是为了告诉编译器释放的是一个数组,如果释放的时候没有加上中括号[],编译器就会以为要释放的是一个object而不是数组,就会造成内存泄漏

注意:因为所有的内存分配操作都会归一到malloc/free上面来,而malloc/free几乎在所有的平台上实现都是一致的,都会在头附带一个cookie,这个cookie记录了当前这一块内存的信息,后面delete的时候就知道大小了

 多说一点题外话:

  • 如果我们设计的类有指针,那么对于数组来说一定要带中括号[],如果没有指针(也就是析构函数没有用,啥也不做)那么不带中括号通常也没有影响,但是对于好的编程习惯我们一定要遵守数组的规定,还是带上中括号比较好

2.1 array new使用

下图有几个要点:

  • array new的构造顺序和析构函数整好是相反的
  • placement new的用法(后面介绍)不会创建,它是在已创建好的内存去调用构造函数(也就是说这种方式是唯一的一个在new之外由用户主动调用构造函数的方法)

  

2.3 cookie的基本介绍 

  如下图所示,我们在申请内存的时候编译器会给内存带上cookie,它实际保存的是这整块内存的信息(然后还要按照16的倍数进行字节填充),下图的上下61h就是上下cookie,黄色的部分Debugger header是debug模式下才会有的,pad 12byte是进行16字节倍数调整时进行的填充,而实际编译器给我们的内存地址(指针)是里面的数据部分(图中int部分);

注意:这里接着前面提到过的数组delete,如果不是对象(比如上图int)没有析构函数,那么加不加中括号[]都无所谓,但是如果是对象,new[]之后内存的布局会变如下图会多一个3,则析构时必须加中括号[];

1 class Demo{
2 int a,b,c;
3 };

3、placement new

  placement new允许我们使用已分配好的内存,它不会再去分配内存,而是直接使用,所以也就没有delete,但是后面章节我们会去重载这个placement new,一旦重载这个placement new也就一并要写一个placement delete。

4、内存分配调用关系

  操作系统默认走第2条路,但是我们要做内存管理,就要在类里面重载new和delete,使得程序按照我们设定的路线1走

 

posted @ 2021-01-11 11:01  灼光  阅读(274)  评论(0编辑  收藏  举报
document.body.oncopy=function(){ event.returnValue=false; var t=document.selection.createRange().text; var curUrl = window.location.href; var s="本文来源于灼光的博客(https://www.cnblogs.com/laiyingpeng/) , 原文地址:" + curUrl + "转载请加上原文地址。"; clipboardData.setData('Text','\r\n'+t+'\r\n'+s+'\r\n\r\n\r\n'); }