上一篇我们提到了new运算符以及它的工作步骤,其实无非是把两项工作独立出来:

1.申请原始内存

2.执行构造函数

delete也涉及了两个工作:

1.执行析构函数

2.释放原始内存

其实标准库提供了另外一种更加高级的手段实现内存的分配和构造,就是std::allocator<T>的职责。

allocator提供了四个操作:

a.allocate(num) 为num个元素分配内存

b.construct(p) 将p所指的元素初始化

destroy(p) 销毁p指向的元素

deallocate(p, num) 回收p指向的“可容纳num个元素”的内存空间

使用示例如下:

#include <iostream>
#include <string>
#include <vector>
#include <memory>
using namespace std; class Test
{
public:
Test() { cout << "Test" << endl; }
~Test() { cout << "Test ..." << endl; } Test(const Test &t)
{
cout << "Copy ....." << endl;
} private:
//Test(const Test &);
//void operator(const Test &);
}; int main(int argc, const char *argv[])
{
allocator<Test> alloc;
Test *pt = alloc.allocate(); //申请三个单位的Test内存
//此时pt指向的是原始内存
{
alloc.construct(pt, Test()); //构建一个对象,使用默认值
//调用的是拷贝构造函数
alloc.construct(pt+, Test());
alloc.construct(pt+, Test());
}
alloc.destroy(pt);
alloc.destroy(pt+);
alloc.destroy(pt+); alloc.deallocate(pt, );
return ;
}

这里注意,allocator提供的allocate函数与operator new函数区别在于返回值,所以前者更加安全。

还有一点,construct一次只能构造一个对象,而且调用的是拷贝构造函数

标准库提供了三个算法用于批量构造对象(前提是已经分配内存)

uninitialized_fill(beg, end, val)   //以val初始化[beg,end)
uninitialized_fill_n(beg, num, val) //以val初始化beg开始的num个元素
uninitialized_copy(beg, end, mem) //以[beg, end)的各个元素初始化mem开始的各个元素

以上三个函数操控的对象都是原始内存示例如下:

#include <iostream>
#include <string>
#include <vector>
#include <memory>
#include <stdlib.h>
using namespace std; class Test
{
public:
Test(int val) :val_(val) { cout << "Test" << endl; } ~Test() { cout << "Test ..." << endl; } Test(const Test &t)
:val_(t.val_)
{
cout << "Copy ....." << endl;
} int val_;
}; int main(int argc, const char *argv[])
{ Test *pt = (Test *)malloc( * sizeof (Test)); Test t(); uninitialized_fill(pt, pt + , t);
cout << pt[].val_ << endl; Test *pt2 = (Test *)malloc( * sizeof (Test));
uninitialized_copy(pt, pt + , pt2); free(pt);
free(pt2);
return ;
}

这里注意标准库的copy、fill函数与uninitialized_系列函数的区别:

copy、fill等操作的是已经初始化对象的内存,因此调用的是赋值运算符

而uninitialized_针对的是原始内存,调用的是拷贝构造函数

OK,我们到此,可以总结出分配原始内存的三种手段:

1.使用malloc

2.使用operator new

3.allocator的allocate函数

这三者从上到下,是一个由低级到高级的过程。

那么执行构造函数,有两种手段:

1.使用placement new运算符

2.使用allocator的construct函数

最后,C语言中的数据都是POD类型,使用原始内存即可,但是C++中的大部分都是非POD类型,需要执行相应的初始化函数,所以,在C++中应该尽可能避免使用memcpy之类的直接操控原始内存的函数

标准库Allocator的使用(一)的更多相关文章

  1. 标准库Allocator的简易实现(二)

    自己实现Allocator并不难,其实只需要改变allocate和deallocate,来实现自己的内存分配策略.   下面是一个std::allocator的模拟实现 #ifndef ALLOCAT ...

  2. 标准库Allocator(三)uninitialized_fill等函数的实现

    前面我们使用了uninitialized_fill,来批量初始化某一段内存. 下面提供三个函数的实现代码,这三个代码的共同点是: 1.遇到错误,抛出异常 2.出现异常时,把之前构造的对象全部销毁 所以 ...

  3. 把《c++ primer》读薄(3-1 标准库string类型初探)

    督促读书,总结精华,提炼笔记,抛砖引玉,有不合适的地方,欢迎留言指正. 问题1:养成一个好习惯,在头文件中只定义确实需要的东西 using namespace std; //建议需要什么再using声 ...

  4. 《C++ Primer》学习笔记【第二部分 C++标准库】

    第8章 IO库 IO对象不能复制,即1.IO对象不能存储在vector或其他容器中   2.如果需要传递或返回IO对象,必须传递或返回指向该对象的指针或引用. 一般情况下,如果要传递IO对象以便对它进 ...

  5. 【转】C++标准库和标准模板库

    C++强大的功能来源于其丰富的类库及库函数资源.C++标准库的内容总共在50个标准头文件中定义.在C++开发中,要尽可能地利用标准库完成.这样做的直接好处包括:(1)成本:已经作为标准提供,何苦再花费 ...

  6. C++标准库<string>简单总结

    C++标准库<string>简单总结 在C++中,如果需要对字符串进行处理,那么它自带的标准库<string>无疑是最好的选择,它实现了很多常用的字符处理函数. 要想使用标准C ...

  7. C++标准库和标准模板库

    转自原文http://blog.csdn.net/sxhelijian/article/details/7552499 C++强大的功能来源于其丰富的类库及库函数资源.C++标准库的内容总共在50个标 ...

  8. [技术] OIer的C++标准库 : 字符串库<string>

    引入 上次我在博客里介绍了OI中可能用到的STL中的功能, 今天我们接着来发掘C++标准库中能为OI所用的部分. 众所周知, OI中经常用到字符串相关的处理, 这时善用字符串库可以使一些操作更加简洁易 ...

  9. C++标准库和标准模板库(转)

    转自原文http://blog.csdn.net/sxhelijian/article/details/7552499 C++强大的功能来源于其丰富的类库及库函数资源.C++标准库的内容总共在50个标 ...

随机推荐

  1. 自定义View Layout过程 (3)

    目录 目录 1. 知识基础 具体请看我写的另外一篇文章:(1)自定义View基础 - 最易懂的自定义View原理系列 2. 作用 计算View视图的位置. 即计算View的四个顶点位置:Left.To ...

  2. 行为型设计模式之中介者模式(Mediator)

    结构 意图 用一个中介对象来封装一系列的对象交互.中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互. 适用性 一组对象以定义良好但是复杂的方式进行通信.产生的相互 ...

  3. MVC学习__修改工程端口号

    有时候,我们会希望修改工程默认生成的端口号,方法如下:

  4. C++嵌套类及对外围类成员变量的访问

    C++嵌套类及对外围类成员变量的访问 在一个类中定义的类称为嵌套类,定义嵌套类的类称为外围类. 定义嵌套类的目的在于隐藏类名,减少全局的标识符,从而限制用户能否使用该类建立对象.这样可以提高类的抽象能 ...

  5. selenium的动作链 actionchains

    click(on_element=None) ——单击鼠标左键 click_and_hold(on_element=None) ——点击鼠标左键,不松开 context_click(on_elemen ...

  6. [转]Google gflags使用说明

    gflags是什么: gflags是google的一个开源的处理命令行参数的库,使用c++开发,具备python接口,可以替代getopt. gflags使用起来比getopt方便,但是不支持参数的简 ...

  7. 【转载】SQL server connection KeepAlive

    1.什么是SQL server TCP连接的keep Alive? 简单说,keep alive 是SQL server在建立每一个TCP 连接的时候,指定了TCP 协议的keepaliveinter ...

  8. linux 系统的负载与CPU、内存、硬盘、用户数监控脚本[marked]

    转载文章 原始出处  在没有nagios监控的情况下,只要服务器能上互联网,就可通过发邮件的方式来提醒管理员系统资源的使用情况. 一.编写linux系统告警邮件脚本 # vim /scripts/sy ...

  9. 八. 输入输出(IO)操作1.输入输出基本概念

    输入输出(I/O)是指程序与外部设备或其他计算机进行交互的操作.几乎所有的程序都具有输入与输出操作,如从键盘上读取数据,从本地或网络上的文件读取数据或写入数据等.通过输入和输出操作可以从外界接收信息, ...

  10. PHP的一些陷阱

    1,空Array为False $a = array() if($a == false) { echo "This will be printed ! ! !" ; } 持续更新中