您的位置:首页 > 编程语言 > C语言/C++

动态数组new、allocate

2015-09-10 17:04 543 查看
new和delete运算符一次分配/释放一个对象,但某些应用需要一次为很多对象分配内存的功能

C++提供了两种一次分配一个对象数组的方法

new表达式语法,可以分配并初始化一个对象数组

allocate类可以将分配和初始化分离

涉及到分配动态数组的类必须定义自己版本的操作,在拷贝、复制以及销毁对象时管理所关联的内存

new和数组

要在类型名后跟一对方括号,其中指明要分配的对象的数目

下例中new分配要求数量的对象,假如分配成功,并返回指向的第一个对象的指针

int *pia = new int[get_size()];//pia指向第一个int


可以使用类型别名表示数组类型来分配一个数组,这样new表达式中不需要方括号

typedef int arrT[42];//arrT表示42个int的数组类型
int *p = new arrt;//p指向第一个int


上述代码中编译器执行的形式是
int *p = new int[42]


分配一个数组会得到一个元素类型的指针

用new分配的数组时,并未得到一个数组类型的对象,而是一个数组元素类型的指针

由于分配的内存不是一个数组类型,一次不能对动态数组调用begin或end。这些函数使用数组维度来返回指向首元素和尾后元素的指针

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

new分配的对象,不管是单个分配的还是数组中的,都是默认初始化的

可以对数组中的元素进行值初始化,方法是在大小之后跟一对空括号

int *pia1 = new int[10]; //10个未初始化的int
int *pia2 = new int[10](); //10个值初始化为0的int
string *pia3 = new string[10]; //10个空的string
string *pia4 = new string[10](); //10个空的string


新标准中可以用元素初始化器的花括号列表

int *pia = new int[10]{0,1,2,3,4,5,6,7};//剩下元素使用值初始化


动态分配一个空数组是合法的

不能创建一个大小为0的静态数组对象,但是当调用new[0]时时合法的:

char arr[0];//错误:不能定义长度为零的数组
char* arr = new char[0];//正确,但arr不能解引用,因为它不指向任何元素


释放动态数组

在指针前加上一个空方括号对:

delete p;//p指向一个动态分配的对象或为空
delete []pa;//pa必须为一个动态分配的数组或空


第二条语句销毁pa指向的数组中的元素,并释放对应内存

数组中元素按照逆序销毁

空方括号对只是编译器此指针指向一个对象数组的第一个元素

对于使用类型别名定义的数组类型,在new表达式中不使用[],但是销毁时也必须使用方括号

typedef int arrT[42];//arrT表示42个int的数组类型
int *p = new arrt;//p指向第一个int
delete []p;


智能指针和动态数组

标准库提供了一个可以管理new分配的数组的unique_ptr版本:

unique_ptr<int[]> up(new int[10]);//up指向一个包含10个未初始化int的数组
up.releasr();//自动用delete[]销毁其指针


类型说明符中的[]说明up是一个指向一个int数组而不是一个int,由于up指向一个数组,当up销毁它管理的指针时,自动使用delete[ ]

当unique_ptr指向一个数组时,可以使用下标运算符来访问数组的元素

for(size_t i =o;i != 10; ++i){
up[i] = i;
}


share_ptr不能直接指向动态数组,需要提供自己定义的删除器

share_ptr不直接支持动态数组的下标运算,其访问元素可以先获得内置指针

for(size_t i =o;i != 10; ++i){
*(sp.get()+i) = i;
}


allocate类<
4000
/h3>

new有一些灵活性上的局限,其中一方面表现在它将内存分配和对象构造结合在一起

当分配大块内存时,我们计划在这块内存上按需构造对象,我们需要将内存分配和对象构造分离

那些没有默认构造函数的类不能用new动态分配数组

allocate类

allocate类在头文件memory中,其将内存分配和对像构造分离开

提供一种类型感知的内存分配方法,其分配的内存是原始的,未构造的

aloocator是一个模板,当一个allocator对象分配内存时,其根据给定对象类型确定恰当的内存大小和对其位置

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


allocator<T> a


定义名为a的allocator对象,它可以为类型为T的对象分配内存

a.allocate(n)


分配一段原始的、未构造的内存,保存n个类型为T的对象

a.deallocate(p,n)


释放从T*指针p中地址开始的内存,这块内存保存了n个类型为T的对象

p必须是一个先前有allocate返回的指针,且n必须是p创建时所要求的大小

在调用deallocate前,用户必须对每个在这块内存中创建的对象调用destroy

a.construct(p,args)


p必须为一个类型为T*的指针,指向一块原始内存

args被传递给类型为T的构造函数,用来在p指向的内存中构造一个对象

a.destroy(p)


p为T*类型的指针,此算法对p指向的对象执行析构函数

allocator分配为构造的内存

allocator分配的内存时未构造的,我们需要再次内存中构造对象

construct函数接受一个指针和零个或多个额外参数,在指定位置构造一个函数

在未未构造对象的情况下使用原始内存是错误的

当用完对象后,要对每个构造的对象用destroy函数销毁他们

我们只能对真正构造了的元素进行destroy

一旦元素被销毁,可以重新使用这块内存保存其它的T

也可以将内存归还给系统,释放内存通过调用deallocate来完成

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

标准库为allocator类定义了两个伴随算法,在未初始化的内存中创建对象,它们都定义在memory头文件中

这些函数在给定目的位置创建元素,而不是由系统分配内存给他们

返回一个指针,指向最后一个构造元素之后的位置

uninitialized_copy(b,e,b2)


从迭代器b和e指出的输入范围中拷贝元素到迭代器b2指定的未构造原始内存中

b2指向的内存必须足够大,能容纳输入序列中元素的拷贝

uninitialized_copy(b,n,b2)


从迭代器b指向的元素开始,拷贝n个元素到b2开始的内存中

uninitialized_fill(b,e,t)


从迭代器b和e指定的原始内存范围中创建对象,对象的值均为t的拷贝

uninitialized_fill(b,n,t)


从迭代器b指向的内存开始创建n个对象,b必须指向足够大的未构造的原始内存,能够容纳给定数量的对象
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息