> 文档中心 > 不使用delete [] 释放内存可不可以

不使用delete [] 释放内存可不可以

大家好,我是小杰。

我们在手捧那两本经典的《C++ primer plus》和《C++ primer》书籍的时候,书上清楚地写着我们在堆中申请和释放内存的时候需要使用new和delete,new [] 和 delete [] 并且必须要配对使用。但是我们只是知道要记住,但是大多都是只知其然,而不知其所以然,那么今天就来深入的聊聊,为什么要配对使用,我要是不配对是使用的话会怎么样。

new和delete到底做了什么

我们先来看一个经典的图:

不使用delete [] 释放内存可不可以

从图中我们可以清楚的看到:

一个C++应用程序在堆中分配内存的过程一共有三种方式:

  1. 应用程序—>C++标准库—>new、delete相关—>malloc和free—>HeapAlloc、VirtualAlloc(操作系统底层API)
  2. 应用程序—>new、delete相关—>malloc和free—>HeapAlloc、VirtualAlloc(操作系统底层API)
  3. 应用程序—>malloc和free—>HeapAlloc、VirtualAlloc(操作系统底层API)
  4. 应用程序—>HeapAlloc、VirtualAlloc(操作系统底层API)

我们可以看到以下几点:

  • 操作系统的API是我们开发应用程序绕不过去的,但是直接调用操作 系统API也不是我们大多数情况需要的,因为我们更多的时候需要写出多平台的代码,而不是针对某一个操作系统来写
  • 尽管我们调用new和delete,但是其本质还是调用的C语言库中使用的malloc和free两个函数(这是我们一会儿要着重关注和研究的)

一个对象的“出生入死”

Object* obj = new Object; //出生··· ···delete obj//消灭

这个是我们new 一个对象然后调用delete来删除这个对象,那么其本质是什么嘞

我们new的操作在编译器眼中大致是什么样子:

Object* obj;try{    void* mem = operator new( sizeof(Object) ); //分配内存    obj = static_cast(mem);//指针转换    obj->Objcect::Object();//原地构造}catch( std::bad_alloc ){    //失败就不执行构造}

operator new 本质上是分配内存,调用的是malloc函数,具体我就不详细写出来啦,感兴趣的可以联系我进行交流。

我们delete的操作在编译器眼中大致是什么样子:

pc->~Object();//先析构operator delete(obj);//释放内存

operator delete本质上是释放内存,调用的是free函数,具体我也就不详细写出来啦。

再来看看new []和delete []

Object* obj = new Object[3];//三次构造··· ···delete[] obj;//三次析构

可以从上面看出来,根据知识迁移可知,当我们申请的是一个对象数组的时候,也同样会经历这个过程,有几个对象就会调用几次构造函数,有几个对象就会调用几次析构函数。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7HBpt106-1640142637990)(https://cdn.jsdelivr.net/gh/Lovelyboyjie/MyPicgo/img/%E6%95%B0%E7%BB%84%E5%AF%B9%E8%B1%A1%E5%86%85%E5%AD%98%E5%9B%BE.png)]

我们申请的内存数组会在数组的头部存储一些相关的信息,具体的大小和编译器的实现有关。但是都会记录这个数组的个数。因此,我们构造次数==析构次数

思考归纳

那么传说中的,如果我们不进行delete [] 来释放内存的话,为什么会出现内存泄漏呢?

其实本质上来说不是这样的,就算我们使用 delete 和 new [] 搭配起来,也不会在这里发生内存泄漏,因为数据头中标记了个数**,所以一定会把这块儿内存free 掉的。**

那内存泄漏是指的什么?

其实这样会导致这三个对象的析构函数只调用一次,也就是最上面的那个析构函数,其他的两个的析构函数不会被调用,所以现在明白了吧,内存泄漏指的是在这个对象中申请的内存,由于没有调用析构函数,导致那块儿内存不会被释放所以泄漏了内存。

举一反三,如果我们new的不是对象而是内置类型,或者说对象中并不含有 指向其他堆内存的指针,那么理论上来说就算不使用delete也不会造成内存泄漏,但是我们平时还是要遵守,这是一个好的习惯,搭配起来的话就不会出现各种各样奇怪的问题,这其实是对自己好。