浅谈c++ new、delete与malloc和free

  malloc与free是C++/C语言的标准库函数,new/delete是C++的运算符。它们都可用于申请动态内存和释放内存。对于非内部数据类型的对象而言,光用maloc/free无法满足动态对象的要求。对象在创建的同时要自动执行构造函数,对象在消亡之前要自动执行析构函数。由于malloc/free是库函数而不是运算符,不在编译器控制权限之内,不能够把执行构造函数和析构函数的任务强加于malloc/free。因此C++语言需要一个能完成动态内存分配和初始化工作的运算符new,以一个能完成清理与释放内存工作的运算符delete。

malloc与new:

  malloc是c语言的库函数,其作用是在内存中开辟一块连续的指定大小的内存空间(注意:调用malloc必须要指定开辟的空间大小),返回指向该被分配内存的指针(该指针为void * ,需要通过强制类型转换将void*指针转换成我们需要的类型)。

//用例
int* ptr = (int*) malloc (sizeof(int)) //分配一个int类型大小的空间
float* ptr2 = (float*) malloc (sizeof(int)) //分配float类型大小空间

一般情况下 malloc总是能成功分配一块连续的内存空间,但当内存耗尽或者内存过于碎片化而不足以开辟固定大小的连续空间的时候,malloc则调用失败,这时候malloc会返回一个空指针NULL,所以每次使用malloc时以防万一都应该先判断其返回指针是否为空防止。

  new是c++提供的一个操纵符(或者说关键字)。其也是用于分配内存的。其调用过程可以分解为三个步骤:

    1、调用operator new(可重载函数)分配内存

    2、在所分配的内存中调用对象的构造函数,构造对象

    3、返回指向该内存空间的指针

  值得一提的是,new内部开辟内存空间的原理也是调用malloc函数,其调用过程被封装在operator new内部,可以说new是在malloc的基础上再封装了一系列功能。与malloc有所区别的是,new在operator new开辟出空间后,会调用对象的构造函数在该空间中构造对象最后返回对象,而malloc只负责开辟空间,并不负责构造对象;并且new 在分配空间失败后并不是返回空指针而是抛出一个 std::bad_alloc 异常。

delete与free:

  free与delete的作用与上面提到的new和delete相反。free函数只需传入指向某一块已分配内存的指针,便能自动释放掉这些内存。而为何调用malloc需要传入开辟空间大小而free不用传入需要释放的空间大小呢?其实原因在于malloc分配空间的时候,不仅会按照传入参数大小分配空间大小,还会在该段内存头部和尾部插入一些额外的信息(俗称cookie),其中包含了内存大小的信息。这样free函数只需要读取该信息,便可以知道要释放的内存大小、范围等。

  而delete调用过程则与new相反,其调用过程也同样可以分解:

    1、调用对象的析构函数

    2、调用operator delete

  delete与new 相对应,其释放内存空间的原理也是调用free函数,其调用过程被封装在operator delete内部,即delete是在free的基础上封装了一系列功能。delete首先调用对象的析构函数,然后底层调用free释放该区域内存。

关于c++内存管理的知识可以阅读候捷老师的一系列书籍以及视频,其中对c++内部原理的解析十分透彻,每一次读都可以读到新的感悟。

原文地址:https://www.cnblogs.com/LEEYATWAH/p/11577587.html

时间: 2024-08-30 01:56:12

浅谈c++ new、delete与malloc和free的相关文章

浅谈new、delete和malloc、free的用法与区别

(1)new和delete用法 如下几行代码: int *pi=new int; int *pi=new int(); int *pi=new int(1024); 第一行这个new表达式在自由存储区中分配创建了一个整形对象,并返回一个指向该对象的地址来初始化指针pi.第二行同一行,只是对指针pi指向的地址的值进行了初始化为0.第三行初始化为1024. 当动态创建的对象用完后必须释放内存,避免造成内存泄漏,可以用delete来完成,new和delete是成对使用的,如下命令释放pi指向的int型

浅谈new与delete(1)

new运算符的作用是完成动态内存分配和初始化工作. 对应的,delete运算符的作用就是完成清理与释放内存工作. 在类构造函数中,可以使用new为数据分配内存,并将内存地址赋予类成员.这样一来,类就可以处理长度不同的字符串,而不用在类设计时就提前固定数组的长度. 但是,如果对象包含成员指针,同时它指向的内存是由new分配的,则当释放用于保存对象的内存时并不会自动释放该对象成员指针指向的内存.因此,当在类构造函数中使用new类来分配内存时,就应该在类析构函数中使用delete来释放分配的内存.如此

浅谈new与delete(2)

上一节介绍了new运算符的常规用法,这一节我们一起来看看定位new运算符的用法. 1.定位new运算符是在已分配的内存空间进行二次分配.例如: char *buffer = new char[512]; Point *p = new (buffer) Point(); //Point为类名 Point *q = new (buffer + sizeof(Point)) Point(); 即:在内存缓冲区buffe中创建对象p.q 2.delete与常规new运算符配合使用,但不能与定位new运算

浅谈C中的malloc和free

在C语言的学习中,对内存管理这部分的知识掌握尤其重要!之前对C中的malloc()和free()两个函数的了解甚少,只知道大概该怎么用——就是malloc然后free就一切OK了.当然现在对这两个函数的体会也不见得多,不过对于本文章第三部分的内容倒是有了转折性的认识,所以 写下这篇文章作为一个对知识的总结.这篇文章之所以命名中有个“浅谈”的字眼,也就是这个意思了!希望对大家有一点帮助! 如果不扯得太远的话(比如说操作系统中虚拟内存和物理内存如何运做如何管理之类的知识等),我感觉这篇文章应该是比较

浅谈 “空指针、野指针、void*”

        Author: JW. Zhou Date: 2014/7/2 一.空指针(0/NULL) 返回NULL和返回0是完全等价的,因为NULL和0都表示空指针,换句话说:空指针是什么,就是一个被赋值为0的指针,在没有被具体初始化前,其值为0:NULL 是一个标准规定的宏定义,用来表示空指针常量. #define NULL 0   或者 #define NULL ((void*)0) 判断一个指针是否为空指针: f(!p) 和 if(p == NULL) ,if(NULL == p)

浅谈RAII&智能指针

关于RAII,官方给出的解释是这样的"资源获取就是初始化".听起来貌似不是很懂的哈,其实说的通俗点的话就是它是一种管理资源,避免内存泄漏的一种方法.它可以保证在各种情况下,当你对对象进行使用时先通过构造函数来进行资源的分配和初始化,最后通过析构函数来进行清理,有效的保证了资源的正确分配和释放.(特别是在异常中,因为异常往往会改变代码正确的执行顺序,这就很容易引起资源管理的混乱和内存的泄漏) 其中智能指针就是RAII的一种实现模式,所谓的智能就是它可以自动化的来管理它所指向那份空间的资源

浅谈移动前端的最佳实践(转)

前言 这几天,第三轮全站优化结束,测试项目在2G首屏载入速度取得了一些优化成绩,对比下来有10s左右的差距: 这次优化工作结束后,已经是第三次大规模折腾公司框架了,这里将一些自己知道的移动端的建议提出来分享下,希望对各位有用 文中有误请您提出,以免误人自误 技术选型 单页or多页 spa(single page application)也就是我们常常说的web应用程序webapp,被认为是业内的发展趋势,主要有两个优点: ① 用户体验好 ② 可以更好的降低服务器压力 但是单页有几个致命的缺点:

C语言中的位拷贝与值拷贝浅谈(转载)

注:C语言实现的PHP变量的赋值过程中,就涉及到了 深拷贝和浅拷贝 位拷贝拷贝的是地址(也叫浅拷贝),而值拷贝则拷贝的是内容(深拷贝).深拷贝和浅拷贝可以简单理解为:如果一个类拥有资源,当这个类的对象发生复制过程的时候,资源重新分配,这个过程就是深拷贝,反之,没有重新分配资源,就是浅拷贝. 位拷贝,及"bitwise assignment"是指将一个对象的内存映像按位原封不动的复制给另一个对象,所谓值拷贝就是指,将原对象的值复制一份给新对象. 在用"bitwise assig

【内存类操作】浅谈内存拷贝异常

结合本人在实际项目中所积累的经验,以及曾经犯过的错误,堆内存操作类函数做一个简单的剖析,抛砖引玉,欢迎大家吐槽. 首先,讲一下内存使用异常发生的几种场景. 1.野指针的使用,使用已经释放的指针,如果向野指针中写内容,就极有可能导致设备重启或任务挂死.因为,正在运行的任务的地址被意外的改写. [避免策略]函数入参要判空,指针使用(包括释放)之前一定要释放. 2.内存函数的错误使用: void *memset(void *s, int ch, size_t n); c语言中在<memory.h>或