C与C++的区别(2)——new和malloc的区别

一、本质区别

在C++中引入更多的关键字,比如:new和delete;
而malloc和free是库函数,需要头文件的支持;

二、申请的空间所在的位置

new关键字为对象分配的空间在自由存储区内。而molloc是从上分配内存;

C/C++内存通常分为:堆、栈、自由存储区、全局/静态存储区、常量存储区;

自由存储区:是C++中通过new和delete动态分配和释放对象的抽象概念;operator new的底层大多由malloc实现,new和delete是可以C++中的关键字,可以对其进行重载(operator new),当new被重载时,内部实现并非只有malloc,此时的内存空间就和堆不同了,这是一块组合的内存空间。

堆:C语言和操作系统的术语,堆是操作系统维护的特殊的一种内存。

三、返回类型

new运算符返回的是对象类型的指针,是一个确定性的类型,类型严格与对象匹配,无须进行类型转换,故new满足安全性;而malloc的返回值是一个void*类型,是一个不确定的类型,需要进行类型的转换。

类型安全很大程度上可以等价于内存安全,类型安全的代码不会试图分配在自己没被授权的内存区域。

四、内存分配失败时返回值

new内存分配失败时,会抛出bac_alloc异常,可以使用异常机制来处理;malloc分配内存失败会返回NULL;所以在c中使用malloc开辟内存都要判断下返回值类型是否为空,来确定内存是否开辟成功;

五、是否需要指定内存大小

使用new申请内存分配时不需要指定内存块的大小,编译器会根据类型信息自行计算;而malloc需要指定所需内存的大小;
 

class A
{
    cout <<"hello";
};
A *p = new A;
A *p = (A*)malloc(sizeof(A));

六、是否调用构造函数、析构函数 

使用new操作符来分配对象内存经历三个阶段

1、通过operator new函数(对于数组是operator new[] 函数)分配一块足够大的,原始的,未命名的内存空间以便于存储特定类型的对象
2、编译器运行相应的构造函数以构造对象,并为其传入初值
3、对象构造完成后,返回一个指向该对象的指针

使用delete操作符来释放对象内存时会经历两个阶段

1、调用对象的析构函数
2、通过函数operator delete释放内存 

使用new和delete会调用对象的构造函数/析构函数。而malloc不会。

七、new与malloc是否可以相互调用

operator new和operator delete的实现可以基于malloc,free;反过来,malloc和free的实现不可以调用new和delete。下面是编写operator new/operator delete的一种简单方式

void* operator new (size_t size)
{
    if(void *p = malloc(size))
    {
        return p;
    }
    else
    throw bad_alloc();
}
void operator delete(void *p)
{
    free(p);
}

 八、对数组的处理

C++提供了new[]与delete[]对数组专门的处理;有new[]分配对应就需要delete[]进行释放,否则只会对数组中的第一个对象进行释放,会造成内存泄露。

A *ptr = new A[10];//分配十个对象
delete[] ptr;

上面已经说过,malloc需要指定开辟内存的大小,它并不知道这块内存上存放的是否是数组,反正就是给你一块内存并且返回一个内存地址;所以如果要动态分配一个数组的内存,还需要我们手动自定数组的大小;

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

九、是否可以被重载

operator new/operator delete可以被重载。标准库是定义了operator new函数和operator delete函数的8个重载版本

//这些版本可能抛出异常
void * operator new(size_t);
void * operator new[](size_t);
void * operator delete (void * )noexcept;
void * operator delete[](void *0)noexcept;
//这些版本承诺不抛出异常
void * operator new(size_t ,nothrow_t&) noexcept;
void * operator new[](size_t, nothrow_t& );
void * operator delete (void *,nothrow_t& )noexcept;
void * operator delete[](void *0,nothrow_t& )noexcept;

而malloc/free不允许重载

十、能够直观地重新分配内存

使用malloc分配的内存后,如果在使用过程发现内存不足,可以使用realloc函数进行内存重新分配实现内存的扩容;realloc首先判断当前的指针所指内存是否有足够的连续空间,如果有,原地扩大可分配的内存地址,并且返回原来的地址指针;如果空间不够,先按照新指定的大小分配空间,将原来有的数据从头到尾拷贝到新分配的内存区域,而后释放原来的内存区域。

new没有这样直观的配套设施来扩充内存。 

猜你喜欢

转载自blog.csdn.net/QX_a11/article/details/89544850
今日推荐