new和malloc的区别

共有10个区别,如表格中所示:

 

1、申请的内存所在位置不同----new在自由存储区,malloc在堆

  new操作符是  从自由储存区(free store)上  为对象  动态分配  内存空间  ,而malloc函数  从上  动态分配  内存空间。

  附:

  自由存储区是C++基于new操作符的一个抽象概念。其定义  是  凡是通过new操作符进行内存申请,该内存即为自由存储区。

    是操作系统的  术语  ,是操作系统所维护的一块特殊内存,用于程序的内存动态分配。在C语言中,使用malloc从堆上分配内存,然后使用free释放已经分配的内存。

  那么,自由存储区  能否与  堆  等价? 

  自由存储区不仅可以是堆,还可以是静态存储区。

  

  特殊地,经过重载的new运算符可以不为对象分配内存。

  

new (place_address)  type

  place_address为一个指针,代表一块内存地地址。当使用上面这种仅以一个地址调用new操作符时,new操作符不分配任何内存,只是简单地返回指针实参,然后在place_address指定地地址进行对象地初始化工作。

 

2、返回类型的安全性不同 -----new返回完整类型指针,malloc返回void*

  new操作符内存分配成功时,返回的是对象类型的指针,类型严格与对象严格匹配,无需进行类型转换,故new是符合类型安全性的操作符。

  malloc内存分配成功时则是返回void*,需要进行强制类型转换成我们需要的类型。

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

 

3、内存分配失败时的返回值----new会抛出异常,malloc返回NULL

  new内存分配失败时,会抛出bac_alloc异常,它不会返回NULL;  

  malloc分配内存失败时,则返回NULL。因此,在C语言中习惯在分配内存之后判断是否分配成功。

int *a = (int *) malloc( sizeof(int));
if( NULL == a)
{
    ...
}

...

  

4、是否需要指定内存块大小----new自动计算,malloc需要显示指出

  new操作符申请内存分配时无须指定内存块的大小,编译器会根据类型信息自动计算

  malloc需要显示地指出内存地尺寸,如上的  sizeof(int)

 

5、是否调用构造函数/析构函数----new调用,而malloc不会

  new操作符来分配对象会经历3个步骤:

  (1) 调用operator new函数(对于数组是operator new[])分配一块足够大的、原始的、未命名的内存空间以便存储特定类型的对象

  (2) 编译器运行相应的构造函数以构造对象,并为其传入初值

  (3) 对象构造完成后,返回一个指向该对象的指针

 

  delete操作符释放对象内存经历2个步骤:

  (1) 调用对象的析构函数

  (2) 编译器调用operator delete (或 operator delete[])函数来释放内存空间。

 

6、对数组的处理-

  C++提供了 new[]和delete[]专门来处理数组类型。

  而至于malloc,它并不知道你在这块内存上要放数组还是啥东西,反正它就给你一块原始的内存,再给你一个内存的地址就完事了。所以在动态分配一个数组的内存,还需要手动指定数组的大小。

 

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

  operator new 或 operator delete 的实现可以基于malloc,而malloc的实现不可以去调用new。

  下面是编写operator new和operator delete的一种简单方式:

void* operator new(sieze_t size)
{
    void* mem=malloc(size);
    if(NULL != mem)
        reutrn mem;
    else throw bad_alloc();
}

void* operator delete(void* mem)noexcept
{
    free(mem);  
}

 

8、是否可以被重载

  operator new / operator delete可以被重载。

  new 和 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 不允许重载

 

9、能否直观地重新分配内存

  malloc分配内存之后,如果在使用过程中发现内存不足,可以使用realloc函数进行内存重新分配,以实现内存的扩充。

  realloc函数先判断当前指针所指的内存是否有足够的连续空间。如果有,原地扩大可分配的内存地址。如果没有,先按照新指定的大小分配空间,将原有数据从头到尾拷贝到新分配的内存区域,最后释放原来的内存区域。

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

 

10、客户处理内存分配不足

  对于malloc,客户不能去编程决定不足以分配时要干什么事,只能看着malloc返回NULL。

 

  对于new,内存分配失败,抛出异常之前,它会调用一个用户指定的错误处理函数,这就是new-handler。

namespace std
{
     typedef void (*new_handler)();
}

  new-handler是一个指针类型,指向了一个没有参数没有返回值的函数,即为错误处理函数。为了指向错误处理函数,客户需要调用set_new_handler函数,它是声明于标准库里的函数。

namespace std
{
     new_handler set_new_handler(new_handler p ) throw();
}
posted @ 2019-12-13 12:41  Litn  阅读(...)  评论(...编辑  收藏