标准库allocator类定义在头文件 <memory>中。它帮助我们将内存分配和构造分离开来,它分配的内存是原始的、未构造的。

类似vector,allocator也是一个模板类,我们在定义一个allocator类类型的时候需要制定它要分配内存的类型,它会根据给定的对象类型来确定恰当的内存大小和对齐位置:

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

allocator类的操作:

allocator类及其算法
allocator<T> a 定义了一个名为a的allocator对象,可以为类型为T的对象分配内存
a.allocate(n) 分配一段原始的、未构造的内存,保存n个类型为T的对象
a.deallocate(p, n) 释放从T*指针p中地址开始的内存,这块内存保存了n个类型为T的对象;p必须是一个先前由allocate成员函数返回的指针,且n必须是创建时候的大小,在destroy之前,用户必须在这块内存上调用destroy函数
a.construct(p, args) p必须是一个类型为T*的指针,只想一块原始内存,args被传递给类型为T的构造函数
a.destroy(p) p为T*类型的指针,此算法对p执行析构函数
  • allcator分配未构造的内存
allocator分配的内存是未构造的,construct成员函数接受一个指针和零个或多个额外参数,在给定的位置构造一个元素,额外的参数用来初始化对象。这些额外参数必须和类型相匹配的合法的初始化器。
为了使用allocate返回的内存,我们必须用construct构造对象。
auto q = p;
alloc.construct(q++); // *q为空字符串
alloc.construct(q++, 10, 'c'); // *q为cccccccccc
alloc.construct(q++, "hi"); // *q为hi

还未构造对象的情况下或者是使用原始内存是错误的:

cout << *p << endl; // 正确,使用string的输出运算符
cout << *q << endl; // 错误,q指向未构造的内存

在这些对象使用结束后,我们使用destroy来销毁这些元素:

while (q != p)
alloc.destroy(--q);

元素被销毁后,如果需要将内存归还给系统,就需要调用deallocate函数:

alloc.deallocate(p, n);

传递给deallocate的指针不能为空,必须指向由allocate分配的内存,而且,n必须为allocate分配时的大小。

  • 拷贝和填充未初始化内存的算法
标准库为allocator类定义了两个伴随算法,可以在未初始化内存中创建对象:
allocator的算法
uninitialized_copy(b, e, b2) 从迭代器b和3
指出的输入范围中拷贝元素到迭代器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必须指向足够大的未构造的原始内存,能容纳给定数量的对象

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

vector<int> vec{0, 1, 2, 3, 4, 5};
auto p = alloc.allocate(vec.size() * 2);
auto q = uninitialized_copy(vec.begin(), vec.end(), p); uninitialize_fill_n(q, vec.size(), 42);

uninitialized_copy在给定位置构造元素,函数返回递增后的目的位置迭代器。因此,一个uninitialized_copy调用会返回一个指针,指向最后一个构造的元素之后的位置。

C++ Primer : 第十二章 : 动态内存之allocator类的更多相关文章

  1. C++ Primer : 第十二章 : 动态内存之shared_ptr类实例:StrBlob类

    StrBlob是一个管理string的类,借助标准库容器vector,以及动态内存管理类shared_ptr,我们将vector保存在动态内存里,这样就能在多个对象之间共享内存. 定义StrBlob类 ...

  2. C++ Primer : 第十二章 : 动态内存之shared_ptr类

    在C++中,动态内存是的管理是通过一对运算符来完成的:new  ,在动态内存中为对象分配空间并返回一个指向该对象的指针,delete接受一个动态对象的指针,销毁该对象,并释放该对象关联的内存. 动态内 ...

  3. C++ Primer : 第十二章 : 动态内存之shared_ptr与new的结合使用、智能指针异常

    shared_ptr和new结合使用 一个shared_ptr默认初始化为一个空指针.我们也可以使用new返回的指针来初始化一个shared_ptr: shared_ptr<double> ...

  4. C++ Primer : 第十二章 : 动态内存之动态内存管理(new和delete)

    C++语言定义了两个运算符来分配和释放动态内存:运算符new分配内存,运算符delete释放new分配的内存. 运算符new和delete 使用new动态分配和初始化对象 在自由空间分配的内存是无名的 ...

  5. C++ Primer : 第十二章 : 动态内存之动态数组

    动态数组的分配和释放 new和数组 C++语言和标准库提供了一次分配一个对象数组的方法,定义了另一种new表达式语法.我们需要在类型名后跟一对方括号,在其中指明要分配的对象的数目. int* arr ...

  6. C++ Primer : 第十二章 : 动态内存之unique_ptr和weak_ptr

    unique_ptr 一个unique_ptr拥有它所管理的对象,与shared_ptr不同,unique_ptr指向的对象只能有一个用户.当unique_ptr被销毁后,它所指向的对象也被销毁. 定 ...

  7. C++ Primer 5th 第12章 动态内存

    练习12.1:在此代码的结尾,b1 和 b2 各包含多少个元素? StrBlob b1; { StrBlob b2 = {"a", "an", "th ...

  8. Linux内核设计与实现 总结笔记(第十二章)内存管理

    内核里的内存分配不像其他地方分配内存那么容易,内核的内存分配不能简单便捷的使用,分配机制也不能太复杂. 一.页 内核把页作为内存管理的基本单位,尽管处理器最小寻址坑是是字或者字节.但是内存管理单元MM ...

  9. C++Primer 第十二章

    //1.标准库提供了两种智能指针类型来管理动态对象,均定义在头文件memory中,声明在std命名空间. // shared_ptr:允许多个指针指向同一个对象. // unique_ptr:独占所指 ...

随机推荐

  1. 类成员函数作为pthread_create函数参数

    from:http://www.cnblogs.com/shijingxiang/articles/5389294.html 近日需要将线程池封装成C++类,类名为Threadpool.在类的成员函数 ...

  2. vs2010设置编辑器背景颜色

    在nopad++中,双击选中某个关键字后,在文档中所有出现该关键字的地方都会高亮,非常方便查看在那些地方有调用. VS2010的默认颜色不够明显(尤其是将系统背景色改为 苹果绿保护色(Hue:85, ...

  3. ODI中通过配置表和自定义逆向工程获取数据库信息

    自定义逆向工程RKM 从配置表meta_db, meta_table, meta_column, meta_key中获取生产库的元数据信息.

  4. IOS四种保存数据的方式

    在iOS开发过程中,不管是做什么应用,都会碰到数据保存的问题.将数据保存到本地,能够让程序的运行更加流畅,不会出现让人厌恶的菊花形状,使得用户体验更好.下面介绍一下数据保存的方式: 1.NSKeyed ...

  5. 12-26 tableView的学习心得

    一:基础部分 UITableView的两种样式: 注意是只读的 1.UITableViewStytlePlain(不分组的) n 2.UITableViewStyleGrouped(分组的) 二:如何 ...

  6. 使用struts2的<s>标签出错

    15:org.apache.struts2.views.jsp.ActionTag 16:JSP 17:18:19:executeResult Server: Resin/3.1.4a Content ...

  7. Android Toast效果

    Android Toast效果是一种提醒方式,在程序中使用一些短小的信息通知用户,过一会儿会自动消失,实现如下: FirstActivity.java package org.elvalad.acti ...

  8. Linux在IA-32体系结构下的地址映射

    1.概览 2.逻辑地址到线性地址 逻辑地址到线性地址的映射在IA-32体系结构中又被称为段式映射.如上图所示,段式映射我们首先需要获取逻辑地址和段选择符,段选择符用于获取GDT中段的基地址,将逻辑地址 ...

  9. BZOJ 3251 树上三角形

    NOIP的东西回成都再说吧... 这题暴力. #include<iostream> #include<cstdio> #include<cstring> #incl ...

  10. HDU-4828 卡特兰数+带模除法

    题意:给定2行n列的长方形,然后把1—2*n的数字填进方格内,保证每一行,每一列都是递增序列,求有几种放置方法,对1000000007取余: 思路:本来想用组合数找规律,但是找不出来,搜题解是卡特兰数 ...