c++ allocator

C++中,动态内存可以用new来实现,即在堆上申请空间,并需要显示释放这块动态内存。当然,也可以用智能指针来实现。

new有一个缺陷,就是把内存分配和对象构造结合在了一起。对于单个对象,这是很方便的,然而对于大块的内存时,可能需要先申请空间,然后陆续执行构造,此时需要将内存分配和对象构造分离开来。allocator类就提供了这样的功能。

先来看一段使用new的例子:

    string* q = new string[10];//申请了10个stirng的空间,并进行默认初始化
    string s;
    string *pp = q;
    while (cin >> s&&pp != q + 10)//再次为这些string赋值
        *q++ = s;
    delete[] q;

可见,对象实际上执行了一次初始化和一次赋值,而实际上初始化的过程是不必要的。

接下来,先用allocator重写一遍,然后再解释一下allocator的操作:

    allocator<string> alloc;//分配string类型的allocator
    auto p = alloc.allocate(10);//分配10个string空间
    auto q = p;
    string s;
    while (cin >> s&&q != p + 10)
        alloc.construct(q++, s);//用输入的值构造元素
    while (q != p)
        alloc.destroy(--q);//逐一销毁元素
    alloc.deallocate(p, 10);//释放内存空间

首先,allocator是一个模板,需要指定分配内存的类型。allocator的主要操作如下:

    alloc.allocate(n);//分配一段原始的内存,保存n个元素,返回首地址
    alloc.construct(p, args);//在p的位置,用args调用构造函数,构造一个对象
    alloc.destroy(p);//对p指向的对象调用析构函数
    alloc.deallocate(p, n);//释放空间,注意n必须与分配的大小参数相等

有几个地方需要注意:

1.分配的内存是没有构造的,使用这些原始内存时错误的,也不能直接对这些内存进行赋值!

2.构造后,如果想释放这块内存,需要先进行销毁,并且必须对构造过的元素进行销毁。

3.分配和释放内存的大小必须相等。

因为allocator可以方便地分配一段内存,于是标准库提供了两组函数,来对整段的区域进行创建对象的操作:

    uninitialized_copy(b, e, b2);//把迭代器b,e之间的元素拷贝到指针b2开始的内存中,b2内存足够大
    uninitialized_copy_n(b, n, b2);//从b起的n个元素拷贝到指针b2开始的内存中
    uninitialized_fill(b, e, t);//同上,对象的值均为t的拷贝
    uninitialized_fill_n(b, n, t);//同上,对象的值均为t的拷贝

不过这些函数看到有人不推荐使用,VS中也会进行报错或者警告,因为是提供给内部使用的函数,前者推荐用copy和copy_n来代替,后者推荐用fill和fill_n来代替。

原文地址:https://www.cnblogs.com/lustar/p/7601009.html