c++内存管理new和delete运算符

本文探讨了C++中的内存管理,重点讲解new和delete运算符的使用,包括为类型分配空间、初始化、释放内存以及new定位表达式的应用。C++中的new和delete比C语言的malloc和free更方便,因为它们可以调用构造和析构函数,并处理分配失败的情况。同时,文章提到了new定位表达式的高效性,以及避免重复释放内存的重要性。
摘要由CSDN通过智能技术生成

我们先了解计算机中的内存在使用中被分为下面几部分:
在这里插入图片描述

内存布局

栈:也叫堆栈,系统自动分配的空间,只要不特殊声明,系统自动在栈上给变量和函数分配内存。栈是自顶向下增长的
堆:可使用动态内存分配的方式申请堆空间,当数据量较大时,栈空间有限,可在堆上申请空间存放;用完需要手动释放!
常量区:用于存放程序中使用到的常量
代码区:存放可执行代码,在执行过程避免频繁的读取磁盘
作为开发者,我们在程序中只需要管理的就是内存中的堆空间了,在c语言中我们使用一组函数来进行管理:c语言内存管理函数,那么在c++中我们会有更好用的内存管理方式吗?

new和delete的使用

肯定是有的,在c++中存在new和delete这两个运算符专门用于内存管理,那么这两个运算符是如何使用的?

  int main()    
  {                       
      int* pi=new int;         
      int* pi1=new int(19);    
      int* arr=new int[10];    
      int i=0;             
      for(i=0;i<10;i++)    
      {    
          arr[i]=i;    
          cout<<arr[i]<<" ";                                                                                                          
      }                         
      cout<<endl;                                
      cout<<"*pi:"<<*pi<<" pi1:"<<*pi1<<endl;    
      //delete[] arr;                            
      delete arr;        
      delete pi;     
      delete pi1;    
      return 0;      
  } 

运行结果:
在这里插入图片描述
上面的关于new的使用:

  1. 为一个类型数据在堆上分配空间 : new 类型名
  2. 为一个类型数据在堆上分配空间并初始化为给定初值:new 类型名(初值)
  3. 为一个数据开辟一定个数的空间: new 类型名 [数据个数]

其中注意int* pi1=new int(19); 是开辟int类型的空间并给初值为19,并不是开辟了19个int类型的空间。
使用完new出来的空间使用完以后就一定要记得使用delete对其分配的空间进行释放:

  1. 释放单个类型数据 :delete 类型指针名
  2. 释放整个数组空间:delete[] 数组指针名

注意:对于数组空间的释放,delete的使用稍有不同,当数组的数据类型为基本类型时delete和delete[]都可对其进行释放,但当数组的数据类型为自定义类型时,delete在使用时只释放了arr[0]的空间,那么就不是我们想要的结果了,所以只能用dalete[] 的方式释放

c++相对于c语言中的内存管理函数有何优势?

new和delete相对于c语言中的malloc、free等函数来讲,new和delete的同时会调用构造和析构函数,并且加入了分配失败的异常机制,这样new和delete在使用起来就非常方便,有大佬模拟了这两个运算符的内部实现,供大家学习一下:new和delete的使用
我们通过学习可以看到new和delete还是通过调用malloc和free来分配和释放内存空间,但是更加便利的是它们会自动调用构造和析构函数
如果数据类型为基本类型,那么是不需要调用构造函数和析构函数的,只有当数据类型为自定义类型时,才会调用构造函数和析构函数。
当开辟或释放自定义类型的数组数据时,开辟了N个数据时,就调用了N次构造函数和N次析构函数。

new定位表达式

当频繁的分配空间时,我们就会频繁的调用malloc,这样机会导致效率降低;new定位表达式则会提前分配好的空间上调用构造函数初始化,不用再次分配空间,以提高效率。

  int main()    
  {    
      char* buffer=new char[1024];//内存池    
      size_t size=0;           
      Data* pd=new(buffer+size)Data(2015,2,22);//在内存池中分配实例化    
      size+=sizeof(Data);    
      Data* pd2=new(buffer+size)Data(2019,2,22);    
      cout<<(void*)buffer<<endl<<pd<<endl<<pd2<<endl;    
        
      pd2->~Data();    
      pd->~Data();  
      //delete buffer;    
      delete[] buffer;                         
      return 0;     
  } 

运行结果:
在这里插入图片描述
通过new定位表达式申请的空间实际并没有开辟新的空间,new(指针)类型申请的地址一般是括号里指针保存的地址,然后调用构造函数,所以无需delete释放,如果要释放,可以通过显示调用析构函数的方式释放。例:pd->~Data();
那么如果delete pd之后会出现问题吗?当然,我们在delete pd会将定位表达式分配给pd的那部分内存释放,然而当你在定位表达式适用完之后释放预先分配的空间时,那这块空间就被重复释放。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值