C++ 动态数组
new和delete运算符一次分配\释放一个对象,但某系应用需要一次为很多对象分配内存的功能。例如vector和string,当重新分配内存时,他们需要一次性为很多元素分配内存。
C++11和标准库提供了两种一次分配一个对象数组的方法。C++定义了另一种new表达式语法,可以分配并初始化一个对象数组。标准库中包含一个名为allocator的类,允许我们将分配和初始化分离。
当一个应用需要可变数量的对象时,我们在StrBlob中使用vector(或其他标准库容器)总是最简单、安全的方法。
(相关资料图)
后面我们会看到使用标准库容器的优势在C++11的新标准下更为显著。
而且使用容器的类可以使用默认版本的拷贝、赋值和析构函数,而分配动态数组的类必须定义自己的版本。
new和数组
为了让new分配一个对象数组,我们要在类型名之后跟一对方括号,在其中指明要分配的对象的数目。
方括号中必须是整型,但不必是常量。
也可以用一个表示数组类型的类型别名
分配一个数组会得到一个元素类型的指针
当我们用上面的方法分配一个数组时,我们并没有得到一个数组类型的对象,而是得到一个数组元素类型的指针。
由于分配的内存并不是一个数组类型,因此不能对动态数组调用begin或end。这些函数使用数组维度来返回首元素和尾后元素的指针。所以我们也不能用范围for语句来处理(所谓的)动态数组中的元素。
注:我们说的动态数组不是数组类型
初始化动态分配对象的数组
默认下,new分配的对象都是默认初始化的。对数组元素初始化的方法是在大小后面跟一对空括号
C++11新标准下可以用元素初始化器的花括号列表
如果初始化器数目大于元素数目,则new表达式失败,不会分配任何内存。本例中会抛出一个bad_array_new_length异常。
虽然我们用空括号对数组中元素进行值初始化,但不能在括号中给出初始化器,这意味着不能用auto分配数组。
动态分配一个空数组是合法的
虽然我们静态数组不能大小为0,但是我们可以为new分配一个大小为0的数组,这时返回的是一个非空指针。
对于零长度的数组我们可以像使用尾后迭代器一样使用这个指针,只是不能解引用,因为他不指向任何元素
释放动态数组
我们使用一种特殊形式的delete释放动态数组
第二个语句的delete是按逆序销毁pa指向数组的元素,并释放内存。
这里的方括号是必须的,他指示编译器此指针指向一个对象数组的第一个元素,如果没有他(或者在单一对象使用了方括号)都是未定义的。
编译器可能不会给出警告此类行为,所以程序在执行过程中可能在没有警告下行为异常。
智能指针和动态数组
为了用一个unique_ptr管理动态数组,我们必须在对象类型后面跟一对空方括号
int[]指出up指向一个int数组而不是int。由于up指向一个数组,当up销毁管理的指针时会自动使用delete[]。
unique_ptr可以使用下标运算符来访问对象
和unique_ptr不同,shared_ptr不直接支持管理动态数组,如果希望他管理一个动态数组,必须提供自己定义的删除器
如果没有提供删除器,那么代码是未定义的。因为默认下shared_ptr会使用delete销毁他指向的对象,但是此代码是一个动态数组,对其使用delete就会产生释放一个动态数组忘记加[]一样的问题。shared_ptr不直接支持动态数组管理
shared_ptr没有定义下标运算符,而且智能指针类型不支持指针算术运算。所以我们必须用get获得一个内置指针,然后用它访问数组元素。
allocator类
new有一些灵活性上的局限,其中一方面表现在他将内存分配和对象构造绑定(类似的,delete将对象析构和内存释放组合在一起)。这一点在分配单个对象时没有问题,因为我们肯定知道这个对象该是什么值。
当分配一大块内存时,我们通常计划在这块内存上按需构造对象。这时我们想要将内存分配和对象构造分离,这意味着我们会先分配一块内存,而只在需要时构造对象(这里需要一定的开销)。
大部分情况下,将内存分配和对象构造绑定会产生浪费
这里我们不仅可能不需要n个string而且就算对于那些使用的string我们都赋值了两次(一次为默认初始化,一次是赋值)
更重要的是,没有默认构造函数的类不能动态分配数组了。
allocator类
allocator类定义在头文件memory中。它帮助我们将内存分配和对象构造分开。
他提供一种类型感知的内存分配方法,他分配的内存是未构造的。
allocator也是一个模板。所以我们定义时要指定对象类型,当allocator对象分配内存时,它会根据给定对象类型来确定恰当的内存大小和对齐位置。
allocator分配为构造的内存
allocator分配的内存时未构造的,我们按需要在此内存中构造对象。
标准库中construct成员函数在给定位置构造一个元素。类似make_shared的参数,这些额外参数必须是和构造的对象的类型匹配的合法初始化器
使用原始内存而未定义对象是错误的!
同样我们要销毁每个构造的元素。
同样我们只能对已经构造的对象进行destroy
我们可以将销毁的空间还给系统
我们传递给deallocator的指针不能为空,必须指向allocate分配的内存,而且传递给deallocator的大小参数必须和调用allocate分配内存时提供的大小参数具有一样的值。
拷贝和填充未初始化内存的算法
标准库还未allocator类定义了两个伴随算法,可以在未初始化内存中创建对象,他们也都定义在memory中
类似copy,uninitialized_copy返回目的位置迭代器。因此uninitialized_copy调用会返回一个指针,指向最后一个元素之后的位置。
相关阅读
精彩推荐
- C++ 动态数组
- 天天即时看!2021京东保价双十二优惠卷满减算不算(京东保价双十二)
- 焦点速读:【视频】一早出门参加亲子活动,他却要面临拘留处罚,咋回事?
- 富瀚微:拟收购眸芯科技49%股权 股票复牌
- 专家群体已被境外势力渗透,大量机密外泄!国家安全,岌岌可危!
- 每日关注!正午·12点 | 不负春光!赏沈城春耕图
- 小区楼顶漏水谁负责维修
- 脱口秀的尺度
- 李晓旭:我通过防守篮板球帮助球队 今年身体恢复不错
- 每日焦点!济南地铁8号线征地,每公顷补偿204万
- 全球即时:虹口区领导调研北外滩区域
- 消费合同纠纷找什么部门?消费纠纷怎么处理?
- 税务部门曝光多起违规操作骗取个税退税案例 焦点速看
- 湖南化工职院举行2023年教学能力比赛
- 环球新资讯:尕怎么读什么意思_尕的正确读音是什么
- 笑果被罚!
- 马龙:这个赛季是小波特生涯防守最好的一个赛季 他想夺冠
- 环球微资讯!李勇:希望成为儿子的榜样
- 黄金英雄官网在哪下载 最新官方下载安装地址
- 赵光义两次北伐,五次大败,损失近三十万精锐 热点评
- 豪鹏科技(001283)盘中异动 股价振幅达8.03% 上涨5.9%(05-17)
- 印度鞭炮工厂爆炸事件死亡人数上升至9人_世界微资讯
- 【环球新要闻】SMM铝晨会纪要:宏观面不确定性仍强 短期铝价弱势震荡
- 一图看懂2023爱奇艺Q1财报!
- whenyousaynothingatall电视剧(whenyousaynothingatall)
- 十城新房成交环比增55.6%_每日简讯
- 华润材料(301090):5月16日北向资金增持2.57万股 环球微动态
- 埃塞俄比亚索马里州发生洪灾 已致45人死亡-世界即时
- 中原消费金融逾期一千天会有什么后果?
- 甲类传染病是指_甲类_世界观点