C和C++区别2---new和delete

(一)内存分布

                               

一个由C/C++编译的程序占用的内存分为以下几个部分: 
1、栈区(stack)— 由编译器自动分配释放 ,存放为运行函数而分配的局部变量、函数参数、返回数据、返回地址等。其操作方式类似于数据结构中的栈。 
2、堆区(heap) — 一般由程序员分配释放, 若程序员不释放,程序结束 时可能由OS回收 。分配方式类似于链表。 
3、全局区(静态区)(static)—存放全局变量、静态数据、常量。程序结束后由系统释放。 
4、文字常量区 —常量字符串就是放在这里的。 程序结束后由系统释放。 
5、程序代码区—存放函数体(类成员函数和全局函数)的二进制代码。

动态分配

在执行程序的过程中动态的分配或者回收存储空间的分配内存的方法。

例如:当我们在定义一个数组时,必须要用一个常量来确定在编译时分配多大的空间。但是在真正使用数组时,我们才会知道我们需要多少内存空间,所以我们要根据程序的需要即时分配,这就牵扯到内存的动态开辟。

(二)C语言  malloc/free 

 void* malloc(size_t size);

开辟一块长度为size的连续内存空间,返回类型为void类型的指针。需要强转,空间申请的大小与形式,跟数据类型无关,它就是动态分配的一段地址。即malloc申请的空间是没有类型概念的,最后赋给具体指向哪种类型的指针,仅需强制转换到相应类型即可。 如果开辟失败,则返回NULL指针。

 void free(void* ptr);

free函数是来释放动态开辟的内存的。 
malloc和free要配套使用,如果没有free则会造成内存泄漏。

malloc怎样获取地址

操作系统中有一个记录空闲内存地址的链表,当操作系统收到程序的申请时,就会遍历链表,malloc函数返回的指针是指向堆里的一块内存;不能初始化;内存不足是,返回NULL。   

(三)C++语言  new   delete

为什么还需要new/delete呢?
           由于malloc/free 是库函数而不是运算符,不在编译器控制权限之内,不能够自动地调用构造函数和析构函数。即无法满足动态对象的要求。因此 C++语言需要一个能完成动态内存分配和初始化工作的运算符new,以及一个能完成清理与释放内存工作的运算符delete。

new运算符不需要类型强转;

new能否进行异常处理,使用更安全。

new 
new运算返回所分配内存单元的起始地址,所以需要把返回值保存在一个指针变量中。若分配不成功,返回NULL,并抛出异常。 
new没有为创建的对象命名,只能通过指针去访问对象或者数组。

delete 
delete <指针变量> 
delete []<动态分配的数组名>

new和delete必须配对使用。 
虽然程序结束后系统会自动释放程序和其中数据所占的内存空间,但是为了在程序运行过程中能够重复使用有限的内存资源,防止系统产生内存泄漏,还是应该即时释放不需要的动态分配的内存单元,以便系统能随时对该内存单元进行分配。 
delete释放内存,只是销毁内存上的对象,但是指针仍然存在,仍然指向原来的内存,保存原来空间的地址。所以我们应该在释放之后将指针置空,以避免后面不小心解引用造成问题。
//变量
int* nNum = new int(5);   //注意申请简单变量,也必须使用指针形式

delete nNum;              //释放空间
nNum = NULL;              //让指针指向空指针,杜绝野地址

//一维数组
int* nNum1 = new int[5];  

delete []nNum1;            //释放空间,记住与变量不同
nNum1 = NULL;

//二维数组
int (*pl)[4]              //必须点明列大小
pl = new int[3][4];

delete []pl;
pl = NULL;

使用new操作符来分配对象内存时会经历三个步骤: 
  第一步:调用operator new 函数(对于数组是operator new[])分配一块足够大的,原始的,未命名的内存空间以便存储特定类型的对象。 
  第二步:编译器运行相应的构造函数以构造对象,并为其传入初值。 
  第三步:对象构造完成后,返回一个指向该对象的指针。

使用delete操作符来释放对象内存时会经历两个步骤: 
  第一步:调用对象的析构函数。 
  第二步:编译器调用operator delete(或operator delete[])函数释放内存空间。

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

(二)new和malloc的区别

  • 属性

new是C++中的关键字,需要编译器支持。,malloc是C和C++的标准库函数,需要头文件支持。他们都可以申请内存。

  • 分配内存的位置

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

自由存储区是C++基于new操作符的一个抽象概念,凡是通过new操作符进行内存申请,该内存即为自由存储区。而堆是操作系统中的术语,是操作系统所维护的一块特殊内存,用于程序的内存动态分配,C语言使用malloc从堆上分配内存,使用free释放已分配的对应内存。自由存储区不等于堆,如上所述,布局new就可以不位于堆中。

  • 分配内存的大小的计算 

使用new操作符申请内存分配时无须指定内存块的大小,编译器会根据类型信息自行计算,而malloc则需要显式地指出所需内存的尺寸。

  • 是否可以初始化

new可以开辟内存并做初始化,初始化对象调用的是构造函数,delete释放内存调用析构函数。malloc不能初始化,malloc只是单纯的开辟内存,free是单纯的释放内存。

  • 申请内存失败

new内存分配失败时,会抛出bac_alloc异常。malloc分配内存失败时返回NULL。

  • 参数

使用new操作符申请内存分配时无须指定内存块的大小,编译器会根据类型信息自行计算。而malloc则需要显式地指出所需内存的尺寸。

  • 返回类型

new操作符内存分配成功时,返回的是对象类型的指针,类型严格与对象匹配,无须进行类型转换,故new是符合类型安全性的操作符。而malloc内存分配成功则是返回void * ,需要通过强制类型转换将void*指针转换成我们需要的类型。

  • 是否可以重载

new支持重载。malloc不能重载。(C语言就不支持重载)

  • 是否可以开辟常量内存

new可以开辟常量内存 ;malloc不能

  • 相互调用

new可以调用malloc ;malloc不能调用new

(三)new和delete用法:

new用法:

          1.     开辟单变量地址空间

               1)new int;  //开辟一个存放数组的存储空间,返回一个指向该存储空间的地址.int *a = new int 即为将一个int类型的地址赋值给整型指针a. 

               2)int *a = new int(5) 作用同上,但是同时将整数赋值为5

          2.     开辟数组空间

               一维: int *a = new int[100];开辟一个大小为100的整型数组空间

               二维: int **a = new int[5][6]

               三维及其以上:依此类推.

         一般用法: new 类型 [初值]

delete用法:

          1. int *a = new int;

               delete a;   //释放单个int的空间

          2.int *a = new int[5];

               delete [] a; //释放int数组空间

 

          要访问new所开辟的结构体空间,无法直接通过变量名进行,只能通过赋值的指针进行访问.

          用new和delete可以动态开辟,撤销地址空间.在编程序时,若用完一个变量(一般是暂时存储的数组),下次需要再用,但却又想省去重新初始化的功夫,可以在每次开始使用时开辟一个空间,在用完后撤销它.

    delete /delete[]

    delete是回收new开辟出的单个对象指针指向的内存。

    delete[ ]是回收new[ ]开辟出的对象数组指针指向大的内存。

    new[ ]开辟数组空间要多出4个字节来存放数组大小。

    delete[ ]和new[ ]要配套使用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值