C++——内存管理(new和delete)详解

目录

C/C++内存管理

案例:变量在内存中到底会在哪?

New和delete

Operator new和operator delete函数

New和delete的原理

对内置类型

对自定义类型

定位new

New/delete和malloc/free的区别


C/C++内存管理

        C/C++内存管理分布图:(从语言的角度来看,数据段也称为静态区,代码段也称为常量区)

        内存大小:理论上,32位计算机内存上限为4GB;64位计算机内存上限可达256T,实际上我们使用计算机一般为8G或16G或者32G,不会很大。

栈和堆细节:  

        栈区先定义的变量放到栈底地址高后定义的变量放到栈顶地址低,因此是栈是向下生长的,堆区则相反

        栈区主要存在局部变量和函数参数,其空间的管理由编译器自动完成,无需手动控制,堆区是自己申请。

        堆大小受限于操作系统,而栈空间一般由系统直接分配。

        栈一般是进行静态分配的,但也可以通过函数_alloca进行动态分配,不过注意,所分配空间不能通过free或delete进行释放,而堆无法静态分配,只能动态分配。

         在C语言中我们用malloc/calloc/realloc和free来在堆上管理堆上的空间,但在c++中进行了更新。在C++中我们用New和delete来管理堆上的空间。

        Malloc和new的最大差别是:C语言malloc失败后会返回NULL,C++New失败后会自动报异常。

        注意:使用malloc是需要头文件malloc.h,只是平时这个头文件已经被其他头文件所包含了,用的时候很少单独引入。

案例:变量在内存中到底会在哪?

请填写下列问题:

        globalVar在哪里?__静态区__  staticGlobalVar在哪里?_静态区___

        staticVar在哪里?__静态区__  localVar在哪里?____

        num1 在哪里?____

        char2在哪里?____ * char2在哪里?___

用数组存储字符串,会在代码段生成一串字符,然后到栈上开辟一段空间,把内容拷贝进去

        pChar3在哪里?____ * pChar3在哪里?_代码段(常量区)___

用指针则是存放 代码段内存放字符串的地址,所以解引用地址会在代码段

        ptr1在哪里?____ * ptr1在哪里?____

prt1变量是在栈区创建的,所以在栈上,但申请的空间在堆上

        sizeof(num1) = __40__;

        sizeof(char2) = _5___;   strlen(char2) = __4__;(sizeof(数组)就是整个数组的大小

        sizeof(pChar3) = _4/8___;   strlen(pChar3) = _4___;(sizeof(指针)则是看几位计算机

        sizeof(ptr1) = __4/8__;

New和delete

        创建单个对象:new 类型(内容)创建数组:new 类型[大小]{内容},开辟类对象的数组时(该类对象有用户写的析构函数,默认生成的不行),会在前面额外开辟4字节空间,用于存放类对象数组有多少个元素,让delete数组时,调用类的析构函数时知道要调用几次。C++把new当做一个操作符而不是函数

        Delete也分为两种,释放单个空间:delete 对象名;释放一个数组:delete[] 对象名

        New和delete的使用方式如下:

        在C++中,我们new一个类对象,编译器会自动调用该类的构造函数。这样就不需要像C语言malloc一个空间然后赋值那么麻烦。Delete也会调用该类的析构函数。

注意:new和delete一定要匹配使用,即new数组要用delete数组来释放。

        如果不匹配使用,对于内置类型没有自己写析构函数的类一般不会出错(默认生成析构函数是系统合成的没有作用的析构函数,所以系统什么也不做,只用释放空间,内置类型同理

        对于有自己写析构函数的类,delete会调用析构函数,而new数组本来应该匹配delete数组来释放,让编译器调用多次析构函数,但如果我们没有匹配使用,如下图,只用了delete a1,编译器只会调用一次析构函数,编译虽然能通过,但是运行会出断言错误。

Operator new和operator delete函数

        Operator new和operator delete函数是系统提供的全局函数,它们实际上是new和delete的底层代码,new底层会调用operator new函数来申请空间;delete底层调用operator delete函数来释放空间

        Operator new底层代码也是通过malloc来开辟空间,即对malloc的封装,如果空间不够,则判断一下malloc是否返回NULL;如果申请内存失败了,这里会抛出bad_alloc类型异常,也就是new失败之后返回的异常。Operator delete同理,是对free的封装

        总之,operator new不是为我们准备的,而是为new准备的,主要是用来返回开辟空间异常的

New和delete的原理

对内置类型

        如果申请的是内置类型的空间,new和malloc,delete和free基本类似,不同的地方是:new/delete申请和释放的是单个元素的空间,new[]和delete[]申请的是连续空间,而且new在申请空间失败时会抛异常malloc会返回NULL

对自定义类型

New:

        调用operator new函数申请空间,然后在申请的空间上执行构造函数,完成对象的构造。

Delete:

        在空间上执行析构函数,完成对象中资源的清理工作,然后调用operator delete函数释放对象的空间

New[N]:

        调用operator new[]函数,在operator new[]中实际调用operator new函数完成对N个对象空间的申请,在申请的空间上执行N次构造函数。

Delete[]:

        在释放的对象空间上执行N次析构函数,完成N个对象中资源的清理。(N是多少编译器会知道,不需要填),然后调用operator delete[]释放空间,实际上在operator delete[]中会调用operator delete来释放空间。

定位new

        定位new表达式是已分配的原始内存空间中调用构造函数初始化一个对象。使用方法为:new(指针,指向开辟的空间)类型(要初始化的值),使用情况如下图所示:

New/delete和malloc/free的区别

区别:

  1. malloc和free是函数,new和delete是操作符
  2. malloc申请的空间不会初始化,new可以初始化
  3. malloc申请空间时,需要手动计算空间大小并传递new只需在其后跟上空间的类型即可,如果是多个对象,[]中指定对象个数即可。
  4. malloc的返回值为void*, 在使用时必须强转new不需要,因为new后跟的是空间的类型。
  5. malloc申请空间失败时,返回的是NULL,因此使用时必须判空;new不需要,但是new需要捕获异常
  6. 申请自定义类型对象时,malloc/free只会开辟空间,不会调用构造函数与析构函数,而new在申请空间后会调用构造函数完成对象的初始化,delete在释放空间前会调用析构函数完成空间中资源的清理。
  • 26
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值