简述malloc和free与new和delete

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/HaloTrriger/article/details/80834812

一、简说

new和delete是C++的关键字,通过new和delete可以在堆上开辟和释放空间。

在C语言中我们通过malloc和free对堆上的内存进行申请和释放。
在C++中,则需要对类的对象进行管理。用new和delete管理对象,new[]和delete[]管理对象数组。它们之间要对应使用。

void Test()
{
    int *p = (int*)malloc(4);
    int *p1 = new int;//p1指向int类型大小的空间
    int *p2 = new int(1);//p2指向int类型大小的空间,并初始化为1
    int *p3 = new int[5];//p3指向有5个int元素的数组类型大小,20字节

    。它们之间要对应使用。delete p1;
    delete p2;
    delete[] p3;
}

二、new和delete

1.new运算符的内部实现

  • 内存分配

调用operator new(size_t)函数,而operator new(size_t)函数又会调用malloc函数申请空间。如果申请失败则抛异常。

  • 初始化

在分配的内存上调用构造函数对对象进行初始化,并返回地址。如果初始化对象失败,则抛异常并调用operator delete(void*)函数释放已申请的内存。

2.delete运算符的内部实现

  • 调用对应类型的析构函数,清理对象,内存释放

  • 调用operator delete(void*)函数,operator delete(void*)会调用free函数释放内存

三、提问三连

  • new和delete与new[]和delete[]有什么不同?

    new[]在调用operator new申请空间会多申请4个字节用于存放元素个数,分配完成指针向后偏移4个字节供用户使用,且会调用N次构造函数分别初始化每个对象。
    而delete[]会向前移动4个字节,得到元素个数,调用N次析构函数清理对象。再调用operator delete释放空间,当然开头4字节也会被释放掉。

  • 如果new和delete[],new[]和delete匹配使用,会怎么样?

    delete[]释放new开辟的空间,会向前偏移4字节读取元素个数,造成释放错误。delete释放new[]的空间,会造成少释放前4字节,并因为不知道该释放多少个元素造成内存泄漏。

  • 如果用free释放new,delete释放malloc申请的空间?

class Person
{
public:
    Person()
    {
        name = new char[8];
    }
    ~Person()
    {
        delete[] name;
    }
    char *name;
};

void Test()
{
    Person*p1 = new Person;
    free(p1);

    Person*p2 = (Person*)malloc(sizeof(Person));
    delete(p2);
}

p1指向new出来的对象。对象通过构造已经初始化。如果直接free(p1),则只对p1的空间free,而对象内name动态开辟的空间没有释放。
p2指向一个malloc出来,对象大小的空间,该块空间没有通过构造函数初始化。delete(p2),会调用析构函数,name没有初始化指向哪块空间,delete[]会造成程序崩溃。

因此,new和delete,new[]和delete[],malloc和free应匹配使用。

四、new和malloc的区别?

new是操作符,malloc是函数。
new在堆上分配空间后会调用构造函数进行初始化,而malloc只管分配空间。
new作用于内置类型和自定义类型,而malloc只能作用于内置类型。
new开辟空间大小由系统计算,而malloc根据传参确定。
new返回值是对应数据类型指针,malloc返回值是void*。
new与delete匹配使用,malloc和free匹配使用。

猜你喜欢

转载自blog.csdn.net/HaloTrriger/article/details/80834812