C++ new 与 malloc的区别 及使用 时注意问题

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

堆: 将程序运行时可使用的 内存空间 称为堆 

一、malloc 与 free

原型:

void* malloc(unsigned int size);
void free(void *p)

malloc:在堆中分配一个长度为 size的连续空间 

void* 是指分配空间起始地址的指针 

如果 malloc函数 未能 成功的执行(eg 内存 不足 ),则返回空指针(null)

使用示例:

int *pi = (int*) malloc(3*sizeof(int));
free(pi);
pi=Null;

二、new 与 delete

介绍三种常用的使用方法 

1、指针变量 = new 数据类型 ;

int *p = new int;

从内存中申请 一个int型 变量(4字节)空间,并将 该内存首地址赋给指针p

2、指针变量 = new 数据类型(初始值);

int *p = new int(4);

4表示 这块内存的初始值,如果不初始化,则p指向的内存里的值是任意的。

3、指针变量 = new 数据类型[数组大小];

new 建立数组类型的变量,指针指向第一个元素的地址。

int *p = new int[10];

使用new为 数组申请内存空间时,不能提供初始值。

4、delete 指针变量

delete p;

使用new建立的数组变量也由delete撤销,其形式为:

delete[]p;

或:

delete p;

三、比较 

相同点:

    malloc 和 new 都用于动态分配内存。

不同点:

1、malloc free是库函数 new delete为关键字

2、new 不仅分配内存,而且会调用类的构造函数,同理delete会调用类的析构函数。而malloc则只分配内存,不会进行初始化类成员 工作,同样free也不会调用析构函数 。new一般由两步构成,分别是new操作和构造,new对应malloc,但new操作可以重载,可以自定义内存分配策略,不做内存分配,甚至分配到非内存设备上,而malloc不能。malloc 只管分配内存,并不能对所得的内存进行初始化,所以得到的一片新内存中,其值将是随机的。

使用new操作符来分配对象内存时会经历三个步骤:

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

第二步:编译器运行相应的构造函数以构造对象,并为其传入初值。

第三部:对象构造完成后,返回一个指向该对象的指针。

使用delete操作符来释放对象内存时会经历两个步骤:

第一步:调用对象的析构函数。

第二步:编译器调用operator delete(或operator delete[])函数释放内存空间。

总之来说,new/delete会调用对象的构造函数/析构函数以完成对象的构造/析构。而malloc则不会

3、效率比较:new可以认为是malloc加构造函数的执行。

4、malloc是标准库函数,需要库文件stdlib.h,new是c++运算符,不需要库文件

5、malloc分配内存前需要手工计算分配多大空间,new能自动计算需要分配的内存空间

6、malloc是最底层函数,不会调用构造函数,函数返回值是void*, new运算符需要调用构造函数,函数    返回相应对象类型的指针

7、new是类型安全的,如int *p=new float[2],编译器会报错。 而malloc不是, int         *p=malloc(2*sizeof(float))编译时编译器无法指出错误

8、malloc可以在C和C++中使用,new只能在C++中使用

9、opeartor new /operator delete可以被重载,而malloc/free并不允许重载

10、在operator new抛出异常以反映一个未获得满足的需求之前,它会先调用一个用户指定的错误处理函数,这就是new-handler

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

C++中的new操作符在分配内存失败时默认的操作是抛出一个内置的异常,而并不是直接返回空指针;这样的话,再把返回值与空指针比较,就没有什么意义了;因为,C++抛出异常之后,就直接跳出new操作符所在的那一行代码,而不再执行后续的代码行了,所以,对new操作符返回值的判断代码就执行不到了;当然,标准C++也提供了抑制抛出异常的方法,使之不再排除内存分配失败的异常,转而直接返回空指针,这是因为比较古老的编译器里面可能没有异常处理机制,不能捕获到异常;如:

int* p = new int[SIZE];
if(p == 0) //检查p是否是空指针;这个判断没有意义;
{
 return -1;
}

所以,在C++中有两种方法来处理new操作符分配内存失败的错误;
1、通过捕获new操作符抛出的异常:

char* p = NULL;
 try
 {
  p = new char[1024];
 }
 catch(const std::bad_alloc& ex)
 {
  //exception handle;
  return -1;
 }

2、抑制异常的抛出:

 char* p = NULL;
 p = new(std::nothrow)char[1024]; //这样的话,如果new分配内存失败,就不会再抛出异常,而是返回空指针了;
 if(p == NULL)                    //这样的判断就有意义了;
 {
  //error handle;
  return -1;
 }

猜你喜欢

转载自blog.csdn.net/Zzhouzhou237/article/details/84560293