c++---c与c++的动态内存管理

本文探讨了C和C++中动态内存管理的使用,包括malloc、calloc、realloc、new和delete。C++的new和delete不仅分配和释放内存,还会调用构造和析构函数。new[]和delete[]用于数组分配,它们会根据元素数量调用相应次数的构造和析构函数。此外,还介绍了operator new和operator delete等函数在内存管理中的作用。
摘要由CSDN通过智能技术生成

c与c++动态内存管理

首先我们来看看它们都是怎么使用的吧。

malloc

void *malloc( size_t size );

calloc

//num:开辟的这块空间有多少个元素
//size:每个元素的字节数
void *calloc( size_t num, size_t size );

realloc

//memblock需要扩容的指针
//size 需要扩充到n个字节
void *realloc( void *memblock, size_t size );

new

new + 需要申请的类型

delete

delete + 指向需要销毁的那块空间的指针

new []

//申请一块内存,用于存放数组
new + 类型[大小]

delete

delete[] + 指针
在C语言中是使用malloc来申请空间,用free来释放空间                          
c语言中不止是有malloc还有calloc,realloc,它们都是c语言中用来动态开辟内存的。

那么他们之间有什么区别呢?

  • malloc:用来申请一块空间,malloc(需要开开辟的空间的字节数),用malloc开辟的空间,没有初始化,就只是一块空间。
  • calloc: 开辟一块空间,并且对这段空间进行初始化。自动将这段空间都初始化为零。
  • realloc:在原来的空间上进行扩容。若是当前内存有足够的空间可以开辟,那么就直接在当前内存的后面开辟,若是内存不足,则需要再重新找一块内存,开辟空间,将之前的值再拷贝过来。然后释放之前的内存空间。

   如果申请成功,返回的都是当前内存的地址,若是申请失败,则返回NULL。
   在不使用这段内存空间后,一定要记得释放这段空间,用free(指向这段空间的指针)。如果不释放,就会造成内存泄漏。表面看着没有什么影响,但是会一直占着内存,直到程序结束。


   c++与c语言一样,也有动态内存开辟的机制,支持程序员自己申请与释放内存。
   在c++中就是使用new和delete,new是用来申请空间,delete用来释放空间。
既然在c语言中已经有了动态开辟内存的机制,为什么在c++中还要引入new和delete呢?
   下面我们就来说一说malloc/free与new/delete的区别

  1. malloc/free是c/c++中的函数,而new/delete则是操作符。从它们的使用方式就可以看出来。malloc/free使用时需要有参数,参数必须得有括号。而new/delete则不需要用括号,后面直接跟需要创建的类型就可以。
  2. malloc/free只是负责开辟空间与释放空间,new与delete则是还需要调用构造函数与析构函数。对开辟的空间要进行初始化,若是要销毁,就需要调用析构函数,来清理空间。
  3. malloc/free需要自己提供需要开辟的字节数,并且返回值为void*,这就需要程序员对接收这块空间的变量类型确定,并且要强转返回的类型为想要的类型,不然就会出错。但是new/delete只需要提供想要开辟的类型即可。而且返回的就是对应类型的指针。不需要再手动强转。

他们的相同点就是都可以申请空间/释放空间。
接下来,我们详细的说明一下它们的用法

new / delete

它们是动态管理对象的。调用构造析构函数。
现在举个例子来验证一下:

#include<iostream>
using namespace std;
class AA
{
public:
    AA()
    {
        cout<<"AA()"<<endl;
    }
    ~AA()
    {
        cout<<"~AA()"<<endl;
    }
};
int main()
{
    AA *p1 = new AA;
    delete p1;
    return 0;
}

这里写图片描述

从上面的这个例子能看出,new/delete在对自定义类型使用的时候,,会自动的调用它们的构造函数与析构函数。创建一个对象就会调用一次构造函数。销毁一个对象的时候也会调用一次其析构函数。那么new[]/delete[]是怎么调用构造析构函数的呢?

 AA *p1 = new AA[3];
    delete[] p1;

new[/delete[的析构与构造的调用情况
   上面这段程序,创建了一个数组,这个数组时候一个存对象的数组,有三个元素。所以需要对每一个对象调用构造函数,并且清理的时候也需要调用三次析构函数。就出现了上图的结果。


   上面介绍的就是new/delete,new[]/delete[]的简单用法。接下来说一说它们的匹配使用问题。
   new/delete是一组,new[]/delete[]是一组。一定是要匹配使用,不可以打乱组合。否则可能会出现内存泄漏甚至程序崩溃。从上面说到的来看,new/delete都是只调用一次,new[]/delete[]调用几次取决于数组中的元素个数。所以,如果出现了不匹配使用,那么调用构造函数与析构函数的次数也就不会匹配,那么就会导致程序出问题。这就是不匹配使用的为什么会导致错误的原因。


   在c++中还有别的动态内存管理的接口。

  • operator new(size_t size)
  • operator delete(size_t size)
  • operator new[](size_t size)
  • operator delete[](size_t size)

operator new/operator delete是一组,匹配使用,负责开辟空间与释放空间。它们的作用相当与c语言中的malloc与free,与它们的用法一样,实际上,operator new/operator delete是malloc/free的一层封装。
operator new[]/operator delete[]是一组,匹配使用,负责开辟连续的数组空间与释放连续的空间。
这四个接口都是函数,不是操作符。看样子是有点像new/delete的运算符重载,其实并不是。new/delete,new[]/delete[]是通过这四个对应的函数来获取内存与释放内存。它们不会调用对象的构造函数与析构函数来初始化对象与清理对象。
具体过程如下所示:
   调用构造函数是new操作符完成的,new又调用operator new开辟内存。而在operator new中有个malloc函数,是负责开辟空间。所以c++中的内存管理就是在c语言的基础上进行了封装与修改得到了c++中的内存管理机制。
new
new[n]是开辟一段连续的空间。这段连续的空间里面存放的是相同的类型数据。new负责调用n次构造函数再调用operator new[],来开辟空间。与new一样,底层实现还是malloc函数。
new[]
delete与new类似,delete操作符负责调用一次析构函数,再调用一次operator delete函数,operator delete负责清理空间,operator delete函数是free函数的封装,所以,其实是free释放的空间。
delete
delete[]这个操作符就有些不一样了。因为delete[]不需要写具体数字,那么,我们怎么知道需要调用几次析构函数呢?
   其实在new[]时,在开辟的空间前四个字节,存储的是n。即当前这个数组中元素的个数。在需要delete这个数组时,只需向前读四个字节,就可以知道当前数组的个数,即知道需要调用几次析构函数。
delete[]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值