new 有一些灵活性上的局限,其中一方面表现在它将内存分配和对象构造组合在了一起。类似的,delete将对象析构和内存释放组合在了一起,我们分配单个对象时,通常希望将内存分配和对象初始化组合在一起。因为在这种情况下,我们几乎肯定直到对象应有什么值。 当分配一大块内存时,我们通常计划在这块内存上按需构造对象,在此情况下,我们希望将内存分配和对象构造分离。这意味着我们可以分配大块内存,但只在真正需要时才真正执行对象创建操作。
allocator类
标准库allocator类型定义在头文件memory中,它帮助我们将内存分配和对象构造分离开。它提供一种类型感知的内存分配方法,它分配的内存是原始的、未构造的。
- allocator<T> a:定义一个名为a的allocator对象,它可以为类型为T的对象分配内存
- a.allocator(n):分配一段原始的、未构造的内存,保存n个类型未T的对象
- a.deallocator(p,n):释放从T*指针p中地址开始的内存,这块内存保存了n个类型未T的对象;p必须是一个先前由alloator返回的指针,且n必须是p创建时所要求的大小。在调用deallocator之前,用户必须对在这块内存中创建的对象调用destroy
- a.construct(p,args):p必须时一个类型为T*的指针,指向一个原始内存;arg被出啊递给类型为T的构造函数,用来在p指向的内存中构造一个对象
- a.destroy§:p为T*类型的指针,此算法对p指向的对象执行析构函数
allocator<string> alloc;
auto const p=alloc.allocator(n);
allocator分配为构造的内存
allocator分配的类是未构造的。我们按需在此内存中构造对象。在新标准中。construct 成员函数接受一个指针和零个或多个额外参数,在给定位置构造一个元素。二外参数用来初始化构造的对象。类似make_shared的参数,这些额外参数必须是与构造的对象的类型匹配的合法的初始化器
auto q=p;
alloc.construct(q++);
alloc.construct(q++,10,'c');
allocator.construct(q++,'hi');
当我们用完对象后,必须对每个构造的元素调用destroy来销毁他们。函数destroy接受一个指针,对指向的对象执行析构函数。
while(q!=p)
alloc.seatroy(--q);
一旦元素被销毁后,就可以宠幸使用这部分内存来保存其他的string,也可以将其归还给系统,释放内存通过调用deallocator来完成
alloc.deallocator(p,n);
拷贝和填充未初始化内存算法
- uninitialized_copy(b, e, b2)从迭代器b和e指出的输入范围中拷贝元素到迭代器b2指定的未构造的原始内存中。b2指向的内存必须足够大,能容纳输入序列中元素的拷贝
- uninitialized_copy_n(b,n,b2):从迭代器b指向的元素开始,拷贝n个元素到b2开始的内存中
- unintialized_fill(b,e,t):在迭代器b和e指定的原始内存范围内创建对象,对象的值均为t的拷贝
- uninitialized_fill_n(b,n,t):从迭代器b指向的内存地址开始创建n个对象。b必须指向足够大的为构造的原始内存,能够容纳给定数量的对象
假定一个int的vector,希望将其内容拷贝到动态内存中。我们将分配一块比vector中元素所占空间大一倍的动态内存,然后将原vector中的元素拷贝到前一半空间,对后一半空间用一个给定值填充
auto p= alloc.alloate(v1.size()*2);
auto q=nuninitialized_copy(vi.begin(),vi.end(),p);
uninitialized_fill_n(q.vi.size(),42);
|