关于new和malloc区别的总结

new和malloc都是常用的申请动态内存方式。他们有以下区别:

1、malloc / free 是C语言的标准库函数,new/delete是c++的运算符(或者说关键字);

2、new/delete比malloc/free更智能,在申请和释放内存时会自动调用对象的构造函数和析构函数(其底层仍靠malloc/free来实现),malloc则只管分配内存并不对所得的内存初始化;

3、返回类型不同,new返回的是指定类型的指针,且自动计算所需内存的大小,malloc返回的是 void* 型,需要手动进行数据类型转换,且内存大小需要手动计算;

如:

int *pint_n = new int[10];//返回类型为 int* 型,申请内存大小为 sizeof(int)*10;

int *pint_m = (int *)malloc(10 * sizeof(int)); //返回的是 void* 型,需手动强转为 int* 型

4、如果申请内存失败,表现形式不同,malloc申请内存失败后返回空指针NULL,new申请失败则抛出异常,直接比较指针是否为空是没有意义的,需要用try、catch的方式捕获异常;

 

5、处理数组的方式不一样,C++提供了new[],delete[],可以通过构造函数和析构函数来逐个处理数组元素,malloc和free则不区分数组还是普通对象,更为佛系。

注意

int *p = NULL;

try {

        p = new int [10];
    
    }
        catch(bad_alloc& a)
    {
        cout<<a.what()<<endl;
    }
    
    delete[] p;
    p = NULL;

    int *q = (int *)malloc(10 * sizeof(int));

    free( q );
    q = NULL;

执行delete删除指针执向的内存后,p变成了不确定指针(悬垂指针),这很容易导致程序运行错误,需要手动指定其值为NULL;

不管使用new还是malloc申请的动态内存,千万不要忘记最后使用对应的delete或free手动释放内存,要不然很容易造成内存溢出,造成不必要的严重后果。

具体分析如下:

malloc(),malloc是从C语言那里继承过来的一个函数,其用于分配一片内存,它的返回结果是一个指向你所需求的内存的指针,其函数原型和使用例子如下:

/*

  函数原型

  其中__size是你要分配的大小,其单位是byte

*/

void* malloc(size_t __size);

// 用例

int* pInt = (int*) malloc(sizeof(int));              // 分配了一个int

double* pDoubleArray = (double*) malloc(sizeof(double) * 5);   // 分配了一个double数组,其大小为5

一般来说,malloc总是能分配出内存。但是也存在山穷水尽,内存不够用的情况。这时候malloc会返回一个空指针(NULL, nullptr)。当使用malloc的时候,最好每次都要判断一下返回的指针是否为空。

已经分配了内存后,当程序运行到某一些时刻,又不想要这些内存了。这时候就要手动释放内存,否则的话就会造成内存泄露。通过free() 函数来释放内存,其函数原型和使用例子如下:

// 原型

void free(void* __ptr);



// 用例

free(pInt);

free(pDoubleArray);

而传给free函数的只是一个指针,不管是分配了一个元素还是分配了一个数组,free总能释放掉这些内存(free 怎么知道你分配的数组的大小?)

接下来说说malloc在分配内存的时候干了什么。
malloc在分配内存的时候,不仅仅会分配你需要的内存大小,它还会在你的内存的头部和尾部加上一些额外的信息(俗称cookie)。

比如说用来DEBUG的信息和你的内存的大小。这就解释了为什么能free掉你的内存,因为它知道你这块内存是多大的。值得一提的是这些Cookie会占用一些内存。

还有一点是malloc只是一个第三方的函数,并不是操作系统的内核函数。如果有额外的需求的话,可以设计自己的malloc。

接下来谈谈new:

new是c++提供的一个操纵符(或者说关键字)。其也是用于分配内存的。其用法例如:

int* pInt = new int(3);           //分配并构造一个int

double* pDoubleArray = new double[5];   //分配了一个double数组,其大小是5



delete pInt;                 //删除单元素

delete[] pDoubleArray;            //删除数组

还是老话题,一般来说程序是能分配出内存的,但是实在山穷水尽了怎么办?这时候程序就会抛出一个std::bad_alloc异常。注意,这是new 和 malloc 的区别之一。但是难能可贵的是C++提供了一个机制来处理bad_alloc异常,其做法如下:

void BadAllocateHandler()

{

  std::cout << "内存分配失败了" << std::endl;

  exit(0);

}

std::set_new_handler(BadAllocateHandler);

BadAllocateHandler是程序员自己写的当分配失败时的处理函数。而set_new_handler是c++提供的机制。一般来说当山穷水尽的时候你所应该做的事只有两件。要么让程序退出,要么想办法从别的地方挖一些内存来继续分配。

new是一个关键字。而对于一个程序来说,一切的动作都将回到函数调用。

所以new的时候到底发生了什么呢?

当new的时候,首先程序会去调用::operator new()这个函数。然后::operator new()中程序会去调用malloc()。 喔!一切都明了了,原来new的本质也是去调用malloc函数。同理,delete的本质是去调用free()函数。

虽然new的本质是去调用malloc,但是new 和 malloc还有一点很大的不同。那就是new 出来内存后,new会把对象给构造出来,而malloc只是分配内存。具体例子如下:

class MyObj {

public:

  public MyObj(int value) : val(value) {}

  int val;

};

MyObj* obj = new MyObj(4);

MyObj* obj1 = (MyObj*) malloc(sizeof(MyObj));

new 的做法是在malloc分配出内存后,编译器会直接调用类的构造函数在这片内存中构造出对象。

注意!只有编译器能直接调用类的构造函数。而使用malloc的话,是无法直接在上面构造出对象的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值