allocator类编程实验


本文是本人大一期间在校学习C++课程时所撰写的实验报告的摘录,由于刚上大学,刚接触计算机编程方面的相关知识,故可能会有很多不足甚至错误的地方,还请各位看官指出及纠正。
本文所涉及到的“教材”指:
电子工业出版社《C++ Primary中文版(第5版)》
如需转载或引用请标明出处。

基本知识

allocator

当分配一大块内存时,我们通常计划在这块内存上按需构造对象。在此情况下,我们只在真正需要时才执行对象的构建操作。

标准库类型allocator可以帮助我们将内存分配和对象构造分离开来,它分配的内存是原始的、未构造的,它定义在头文件memory中。下面是allocator的一些相关操作:

allocator<T> a					//定义一个名为a的allocator对象,可以为类型为T的对象分配内存
a.allocate (n)					//分配一段原始的、未构造的内存,保存n个类型为T的对象
a.destroy (p)					//p为T*类型的指针, 对p指向的对象执行相应的析构函数
a.deallocate (p, n)				//释放从T*指针p中地址开始的内存,其中n必须是p创建时的大小。在调用该函数前,必须对该内存中的每个对象调用destroy
a.construct (p, args)			//T*指针指向一块原始内存,arg被传递给类型为T的构造函数,在p所指内存中构造对象

定义一个allocator时必须指明其可以分配的对象类型。当一个allocator对象分配内存时,它会根据给定的对象类型来确定恰当的内存大小和对其位置:

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

allocator分配的内存是未构造的,我们按需在此内存中构造对象。construct成员函数接受一个指针和零个或多个额外参数,在给定位置构造一个元素。额外参数用来初始化构造的对象。例如:

alloc.construct(q++);				//*q为空字符串
alloc.construct(q++, 3, 'c');		//*q为ccc                                                                                                                                  
alloc.construct(q++, "hi")			//*q为hi

在我们用完对象后,必须对每个构造的对象调用destroy来销毁它们。一旦元素被销毁后,就可以重新使用这部分内存来保存其他string,也可以将其归还给系统。释放内存通过调用deallocate来完成。其中的指针参数必须指向allocate分配的内存,而且传递给deallocate的大小参数也必须和调用allocated分配内存时提供的大小参数具有一样的值。

uninitialized_copy、uninitialized_fill等函数

标准库还为allocator类定义了两个伴随算法,可以在未初始化内存中创建对象,这些函数定义在memory头文件中,描述如下:

uninitialized_copy (b, e, b2)		//从迭代器b和e指定的范围中拷贝元素到迭代器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个对象,对象的值均为t的拷贝

uninitialized_copy接受三个迭代器参数。前两个表示输入序列,第三个表示这些元素要拷贝到的目的空间。传递给uninitialized_copy的目的位置迭代器必须指向未构造的内存返回递增后的目的位置迭代器,因此,一次uninitialized_copy调用会返回一个指针,指向最后构造的元素之后的位置
uninitialized_fill则更像是填充函数。
这些函数的目标地址都必须足够大,能容纳要创建或拷贝的对象。

示例程序

usealloc.cpp主要展示了allocator的相关用法及使用数组和allocator的区别,usealloc2.cpp主要展示了使用uninitialized_copy和uninitialized_fill使用方法。

示例代码

usealloc.cpp

#include <string>
using std::string; 

#include <memory>		//使用allocator
using std::allocator;

#include <cstddef>		//使用size_t
using std::size_t; 
                                                                                                                                                 
#include <iostream>
using std::cout; using std::endl; 

#include <fstream>		//使用文件流
using std::ifstream;

int main() 
{
	const size_t n = 100;
	allocator<string> alloc;			//alloc是一个可以分配string的对象
	string *p = alloc.allocate(n);		//p指向alloc分配的n个没有初始化的的string的内存空间的开始
	
	string *q = p;						//q指向最后构造的元素之后的位置
	alloc.construct(q++, string());		//在q指向的位置(即p)处,初始化一个空string,再递增q的位置
	cout << *(q - 1) << endl;			//输出上面的string
	
	alloc.construct(q++, string(10, 'c')); //初始化下一个string,由十个‘c’组成
	cout << *(q - 1) << endl;			//输出上面的string
	
	alloc.construct(q++, string("hi"));    //初始化下一个string,是“hi”
	cout << *(q - 1) << endl;			//输出上面的string                                                                                                                                                           
	
	cout << *p << endl;					//因为p指向第一个字符串的位置,所以可以解引用输出
	while (q != p)						//析构上述初始化的string
		alloc.destroy(--q);				//因为q指向尾后,所以先递减q,再对其指向的string执行对应的析构函数
	
	alloc.deallocate(p, n);				//回收之前分配的空间
	
	p = alloc.allocate(n);				//重新分配n个没有初始化的的string的内存空间
	string s;							//s用于临时存储读入
	q = p;								//q指向上面分配空间的第一个string
	ifstream in("data/storyDataFile");	//声明一个文件输入流in,读取目录下data/storyDataFile的内容
	while (in >> s && q != p + n)
		alloc.construct(q++, s);		//当有读入一个string时才初始化一个string
	size_t size = q - p;				//指示有多少个string初始化

	cout << "read " << size << " strings" << endl;
	
	for (q = p + size - 1; q != p; --q)
		alloc.destroy(q);				//析构每一个已初始化的string
	alloc.deallocate(p, n);				//回收之前分配的空间
                                                                                                                                                    
	//使用数组代替上面的实现
	in.close();							//关闭文件输入流in
	in.open("data/storyDataFile");		//重新打开文件输入流in
	p = new string[n];					//初始化n个string,构成数组,p指向第一个的位置
	q = p;
	while (in >> s && q != p + n)
		*q++ = s;						//对q指向的string重新赋值
	size = q - p;						//指示有多少个string被重新赋值

	cout << "read " << size << " strings" << endl;

	delete[] p;							//用delete[]释放数组

	system("pause");
	return 0;
}

运行结果:
创建data/storyDataFile文件:
文本
运行程序,结果如下:
结果1
说明in文件读入流以任意空白作为是否读取一个string的判断依据。

usealloc2.cpp

#include <cstddef>
using std::size_t;

#include <string>                                                                                                                                                                 
using std::string; 

#include <vector>
using std::vector; 

#include <memory>		//使用allocator、uninitialized_copy等
using std::uninitialized_copy;
using std::allocator; using std::uninitialized_fill_n;

#include <iostream>
using std::cout; using std::endl;

int main()
{
	int temp[] = {1,2,3,4,5,6,7,8,9};
	vector<int> vi(temp, temp + sizeof(temp)/sizeof(*temp));

	allocator<int> alloc;
	int *p = alloc.allocate(vi.size() * 2);		//alloc所占有的空间是vi的两倍,其被p指向

	int *q = uninitialized_copy(vi.begin(), vi.end(), p);	//将vi中的元素都拷贝到alloc中,q指向尾后元素                                                                                                                                                 

	uninitialized_fill_n(q, vi.size(), 42);		//将剩下的空间都初始化为42

	for (size_t i = 0; i != vi.size(); ++i)		//输出前一半元素
		cout << *(p + i) << " ";
	cout << endl;

	for (size_t i = 0; i != vi.size(); ++i)		//输出后一半元素
		cout << *(q + i) << " ";
	cout << endl;

	alloc.deallocate(p, vi.size() * 2);

	system("pause");
	return 0;
}

运行结果:
结果2

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值