前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >使用new运算符进行动态内存分配

使用new运算符进行动态内存分配

原创
作者头像
Alan_1
发布2023-04-30 12:18:49
4730
发布2023-04-30 12:18:49
举报
文章被收录于专栏:Alan的blogAlan的blog
  • 编译器使⽤三块独⽴的内存:⼀块⽤于 静态变量static(可能再细分),⼀块⽤于⾃动变量,另外⼀块⽤于动态存储new。
  • 动态内存由运算符new和delete控制
  • 将函数中局部(指针)变量的连接性声明为外部的extern,则文件中位于该声明后面的所有函数都可以使用该局部(指针)变量,例子:extern float* p_fees;
  • 使用new运算符初始化
  • 如果要为内置的标量类型(如int或double)分配存储空间并初始化,可在类型名后⾯加上初始值,并将其⽤括号括起:
  • 要初始化常规结构或数组,需要使⽤⼤括号的列表初始化, 这要求编译器⽀持C++11。
代码语言:txt
复制
 ![image-20211026025147544](C:\Users\ALAN.XUAN\AppData\Roaming\Typora\typora-user-images\image-20211026025147544.png)
  • 可将列表初始化⽤于单值变量:
代码语言:txt
复制
 ```c++
代码语言:txt
复制
 int *pin=new int {6};	//*pi set to 6;
代码语言:txt
复制
 double *pdo=new double {99.99};		//*pd set to 99.99;
代码语言:txt
复制
  1. new失败时

new可能找不到请求的内存量。在最初的10年中,C++在这种情况 下让new返回空指针,但现在将引发异常std::bad_alloc。

  1. new:运算符、函数和替换函数
  2. 运算符new和new []分别调⽤如下函数:
代码语言:txt
复制
 ```c++
代码语言:txt
复制
 void* operator new(std::size_t);    //new
代码语言:txt
复制
 void* operator new[](std::size_t);   //new[]
代码语言:txt
复制
代码语言:txt
复制
 - 这些函数被称为分配函数(alloction function),它们位于全局名称空间中。同样,也有由delete和delete []调⽤的释放函数(deallocation function):
代码语言:txt
复制
   ```c++
代码语言:txt
复制
   void* operator delete(std::size_t);    //delete
代码语言:txt
复制
   void* operator delete[](std::size_t);    //delete[]
代码语言:txt
复制
  • 基本语句:
代码语言:txt
复制
 int* pi=new int;将被替换为
代码语言:txt
复制
 ```c++
代码语言:txt
复制
 //1
代码语言:txt
复制
 int* pi=new int;
代码语言:txt
复制
 //将被替换为
代码语言:txt
复制
 int* pi=new(sizeof(int));
代码语言:txt
复制
 //2
代码语言:txt
复制
 int* pa=new int[40];
代码语言:txt
复制
 //将被替换为
代码语言:txt
复制
 int* pa=new(40*sizeof(int));
代码语言:txt
复制
  1. 定位new运算符
  2. new负责在堆(heap)中找到一个足以能够满足要求的内存块。
  3. 定位new 运算符能够指定要使用的位置
  4. 可以使⽤这种特性来设置其内存管理规程、处理需要通过特定地址进⾏访问的硬件或在特定位置创建对象。
  5. 要使⽤定位new特性,⾸先需要包含头⽂件new,它提供了这种版本 的new运算符的原型;然后将new运算符⽤于提供了所需地址的参数。
  6. 使⽤定位new 运算符时,变量后⾯可以有⽅括号,也可以没有。
  7. new的4种用法:
代码语言:txt
复制
 ![image-20211026031152962](C:\Users\ALAN.XUAN\AppData\Roaming\Typora\typora-user-images\image-20211026031152962.png)
代码语言:txt
复制
 出于简化的⽬的,这个⽰例使⽤两个静态数组来为定位new运算符提供内存空间。因此,上述代码从**buffer1中分配空间给结构chaff**,从 **buffer2中分配空间给⼀个包含20个元素的int数组。**
代码语言:txt
复制
 - 使⽤**常 规new运算符**和**定位new运算符**创建动态分配的数组。
代码语言:txt
复制
   ![image-20211026031700368](C:\Users\ALAN.XUAN\AppData\Roaming\Typora\typora-user-images\image-20211026031700368.png)
代码语言:txt
复制
   ![image-20211026031746677](C:\Users\ALAN.XUAN\AppData\Roaming\Typora\typora-user-images\image-20211026031746677.png)
  • 定位new运算符确实将 数组p2放在了数组buffer中,p2和buffer的地址都是00FD9138。然⽽,它 们的类型不同,p1是double指针,⽽buffer是char指针(顺便说⼀句,这 也是程序使⽤(void *)对buffer进⾏强制转换的原因,如果不这样做, cout将显⽰⼀个字符串)同时,常规new将数组p1放在很远的地⽅,其 地址为006E4AB0,位于动态管理的堆中。
  • 第⼆个常规new运算符查找⼀个新的内存 块,其起始地址为006E4B68;但第⼆个定位new运算符分配与以前相同 的内存块:起始地址为00FD9138的内存块。定位new运算符使⽤传递给 它的地址,它不跟踪哪些内存单元已被使⽤,也不查找未使⽤的内存 块。这将⼀些内存管理的负担交给了程序员。
  • 对于常规new运算符, 下⾯的语句释放起始地址为006E4AB0的内存块,因此接下来再次调⽤ new运算符时,该内存块是可⽤的:
代码语言:txt
复制
 delete [] pd1;
代码语言:txt
复制
 - 不能使⽤delete来释放使⽤定位new运 算符分配的内存。
代码语言:txt
复制
 - 事实上,在这个例⼦中不能这样做。buffer指定的内存是**静态内存**,⽽delete只能⽤于这样的指针:**指向常规new运算符分配的堆内存。**也就是说,数组buffer位于delete的管辖区域之外,
代码语言:txt
复制
 - 如果buffer是使⽤常规new运算符创建的,便可以使⽤常 规delete运算符来释放整个内存块。
 - 定位new运算符的另⼀种⽤法是,**将其与初始化结合使⽤**,从⽽将 信息放在特定的硬件地址处。
  • 定位new运算符的⼯作原理。基本上,它只是返回传递给它的地址,并将其强制转换为void *,以便能够赋给任何指针类 型。但这说的是默认定位new函数,C++允许程序员重载定位new函数。
  • 定位new的其他形式:

标准定位 new调⽤⼀个接收两个参数的new()函数:

定位new函数不可替换,但可重载。它⾄少需要接收两个参数,其 中第⼀个总是std::size_t,指定了请求的字节数。这样的重载函数都被称为定义new,即使额外的参数没有指定位置。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档