当前位置: 首页 > news >正文

C++中的内存管理(二)

文章目录

  • new和数组
    • 初始化动态分配对象的数组
    • 释放动态数组
    • 智能指针和动态数组
  • allocator
    • allocator类
    • 初始化
    • 摧毁对象
    • 归还内存
    • 拷贝和填充未初始化内存的算法

某些应用需要一次性为很多对象分配内存的功能。C++中提供了两种一次分配一个对象数组的功能:newallocator,其中后者允许将分配和初始化分离,提供更好的性能和更灵活的内存管理能力。

大多数应用应该使用标准库容器而不是动态分配的数组。使用容器更为简单,更不容易出现内存管理错误并且可能拥有更好的性能。

使用容器的类可以使用默认的拷贝、赋值和析构操作。分配动态数组的类必须定义自己版本的操作,在拷贝、复制以及摧毁对象时管理所管理的内存。

new和数组

//get_size()即使为0,也是合法的。但是不能解引用,类似尾后指针
int *pia = new int[get_size()]; typedef int arrT[42];
int *p = new arrT; //分配一个42个int的数组,p指向第一个int

虽然我们通常称new T[]分配的内存为动态数组,但这种叫法有些误导。我们得到的并非要给数组类型的对象,而是得到一个数组元素类型的指针(没有数组的维度)。因此不能对动态数组调用begin和end,也不能使用范围for语句来处理动态数组中的元素。

初始化动态分配对象的数组

默认情况下,new分配的对象都是默认初始化的。可在后面跟一个()进行值初始化:

int *pia = new int[10]; //10个未定义
int *pia2 = new int[10](); //10个0
string *psa = new string[10]; //10个空string
string *psa2 = new string[10](); //10个空string

在新标准中,还可以使用初始化器{}

int *pia3 = new int[10]{0, 1, 2}; //剩余元素进行值初始化
string *psa3 = new string[10]{"a", "an", string(3, 'x')};

释放动态数组

delete p; //p为动态对象或空
delete [] pa; //pa为一个动态分配的数组或空,逆序摧毁数组中元素

智能指针和动态数组

  • unique_ptr
//无需提供自定义删除器,类型为T[]
unique_ptr<int []> up(new int[10]);
up.release(); //自动使用delete []摧毁其指针//unique_ptr可以使用下标运算符
for(size_t i = 0; i != 10; ++i)up[i] = i;
  • shared_ptr
//不直接支持管理动态数组,类型为T,必须提供删除器
shared_ptr<int> sp(new int[10], [](int *p){delete [] p;});//不支持下表访问
for(size_t i = 0; i != 10; ++i)*(sp.get() + i) = i;

allocator

new在灵活性上有一定的局限性。其将内存分配和对象构造组合在了一起。delete同理。当分配一块大内存时,通常计划按需构造对象,因此需要将内存分配和对象构造分离。

string *const p = new string[n];
string s;
string *q = p;
while(cin >> s && q != p + n)*q++ = s;
const size_t = q - p;
delete [] p;
  • new表达式分配并初始化了n个string。但是,我们可能并不需要n个string;
  • 对于确实需要使用到的对象,也在初始化后立即赋予了新值。每个使用到的元素都被赋值了两次;
  • 对于没有默认构造函数的类,不能使用动态数组。

allocator类

当一个allocator对象分配内存时,它会根据给定的对象类型来确定恰当的内存大小和对齐位置:

allocator<string> alloc; //可以分配string的对象
auto const p = alloc.allocate(n); //分配n个未初始化的string

在这里插入图片描述

初始化

auto p = q;
alloc.construct(q++); //string默认构造函数构建q,q++
alloc.construct(q++, 10, 'c'); //q指向“ccc...”
alloc.construct(q++, "hi"); //q指向"hi"cout << *p << endl; //ok
cout << *q << endl; //err,当前q还未构造

摧毁对象

当我们使用完对象之后,必须对每个构造的元素调用destroy来摧毁他们。值得注意的是,只有真正构造了的元素才能使用该操作。

while (q != p)alloc.destroy(--q);

归还内存

一但元素被摧毁之后,就可以重新使用这部分内存,也可以通过deallocate来归还内存:

alloc.deallocate(p, n);

传递给deallocate的指针不能为空,必须指向alloc分配的内存,n也必须和分配的一致。

拷贝和填充未初始化内存的算法

在这里插入图片描述
假定有一个int的vector,希望将其内容拷贝到动态内存中。我们可以分配一块必vector元素所占空间大一倍的动态内存,然后将袁vector的元素拷贝到前一半空间,多一半用一个值填充:

auto p = alloc.allocate(vi.size() * 2);
auto q = uninitialized_copy(vi.begin(), vi.end(), p); //返回最后一个构造元素之后的指针
uninitialized_fill_n(q, vi.size(), 42);
http://www.dtcms.com/a/342737.html

相关文章:

  • 第四章:大模型(LLM)】07.Prompt工程-(6)受限生成和引导生成
  • 机械试验台功能量具平台:铸铁工装平台
  • 阿里云对象存储OSS之间进行数据转移教程
  • 小迪安全v2023学习笔记(六十八讲)—— Java安全原生反序列化SpringBoot攻防
  • iOS沙盒机制
  • 【系统信息相关】datecal命令
  • React + Antd+TS 动态表单容器组件技术解析与实现
  • (栈)Leetcode155最小栈+739每日温度
  • Python爬虫实战:研究puzzle,构建谜题类数据采集分析系统
  • 编程语言与存储过程:业务处理的速度与取舍
  • 3ds Max 渲染动画总模糊?
  • 基于stm32的智能建筑能源管理系统/基于单片机的能源管理系统
  • 【Java SE】认识数组
  • 【Protues仿真】基于AT89C52单片机的舵机和直流电机控制
  • 【新启航】3D 扫描逆向抄数全流程工具与技能:从手持设备到 CAD 建模的 10 项核心配置解析
  • windows10安装playwright
  • Workerman在线客服系统源码独立部署
  • 笔记本电脑Windows+Ubuntu 双系统,Ubuntu无法挂载Windows的硬盘 报错问题解决
  • TDengine IDMP 运维指南(常见问题)
  • 天眼应急案例(二)
  • 一句话生成uml图相关操作
  • MTK平台蓝牙学习-- 如何查看蓝牙连接参数
  • Vitest 测试框架完全指南 – 极速单元测试解决方案
  • selenium3.141.0执行JS无法传递element解决方法
  • 【自记】Power BI 中 VALUES 和 DISTINCT 在可接收的参数类型上的区别。
  • 【每天一个知识点】 时空组学(Spatiotemporal Omics)
  • Nginx学习记录
  • 移动端网页调试实战 IndexedDB 与本地存储问题的排查与优化
  • 阿里云 AI 搜索 DeepSearch 技术实践
  • 网络流量分析——基础知识(二)(Tcpdump 基础知识)