此部分包括智能指针、new/malloc delete/free、allocator
先记allocator:
new有一些灵活性上的局限,其中一方面表现在它将内存分配和对象构造组合在一起。delete将对象析构和内存释放组合在一起。
一般情况下,将内存分配和对象构造组合在一起可能会导致不必要的浪费。可能会使一个对象被赋值两次:一次默认构造,一次另一种构造。
allocator类:
标准库allocator类定义在头文件memory中,它帮助我们将内存分配和对象构造分离开来。它提供一种类型感知的内存分配方法,它分配的内存是原始的、未构造的。
allocator是一个模板。为了定义一个allocator对象,我们必须指明这个allocator可以分配的对象类型。当一个allocator对象分配内存时,它会根据给定的对象类型来确定恰当的内存大小和对齐位置。
allocator方法:
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分配的内存是未构造的。我们按需要在此内存中构造对象。在新标准库中,construct成员函数接受一个指针和零个或多个额外参数,在给定位置构造一个元素。额外参数用来初始化构造的对象。类似make_shared的参数,这些额外参数必须是与构造的对象的类型相匹配的合法的初始化器。
还未构造对象的情况下就使用原始内存是错误的。行为未定义。
当我们用完对象后,必须对每个构造的元素调用destroy来销毁它们。函数destroy接受一个指针,对指向的对象执行析构函数。
一旦元素被销毁后,就可以重新使用这部分内存来保存其它的对象,也可以将其归还给系统。释放内存通过调用deallocate来完成。
我们传递给deallocate的指针不为空,它必须指向由allocate分配的内存。而且,传递给deallocate的大小参数必须与调用allocate分配内存时提供的大小参数具有一样的值。
拷贝和填充未初始化内存的算法:
标准库还为allocator类定义了两个伴随算法,可以在未初始化内存中创建对象。
这些函数在给定目的位置创建元素,而不是由系统分配内存给它们。
uninitialized_copy( b, e, b2) 从迭代器b和e指出的输入范围中拷贝元素到迭代器b2指定的未构造的原始内存中。b2指向的内存必须足够大,能容纳输入序列中元素的拷贝。
uninitialized_copy_n(b, n, b2) 从迭代器b指向的元素开始,拷贝n个元素到b2开始的内存中。
uninitialized_fill( b, e, t) 在迭代器b和e指定的原始内存范围中创建对象,对象的值均为t的拷贝。
uninitialized_fill_n( b, n, t) 从迭代器b指向的内存地址开始创建n个对象。b必须指向足够大的未构造的原始内存,能够容纳给定数量的对象。