引言:
- 在介绍allocator之前,先看一下下面的案例
一、allocator类简介
- new表达式分配了50个string。但是我们可能没有使用到50个string。但是那些没有被使用到的string也被初始化了并且申请了内存空间,这样就造成了内存的浪费
string *const p = new string[50]; string s; string *q = p; while (cin >> s && q != p + n) //输入stirng *q++ = s; delete[] p;//释放p指向的数组
- 头文件
- 标准库allocator类帮助我们将内存分配和对象构造分离开来。它分配的内存是原始的、未构造的
- a.address(x); //返回某个对象的地址,等同于&x
- a.max_size();//返回可成功配置的最大量
三、allocate函数使用方法:
- 第一步:使用allocator<>模板定义一个特定类型的allocator类对象
- 第二步:使用allocate()函数分配一块指定大小的内存,该内存中的对象都是未构造的
- 第三步:使用construct()函数对指定位置的元素就行初始化
- 第四步:如果某个位置的元素不想使用就调用destroy()函数来销毁它们(但是空间还没有释放)。如果该位置需要重新使用就调用allocate()函数来初始化。如果不再使用进行下一步
- 第五步(依情况而选):元素销毁之后,可以调用deallocate()函数来释放内存
- 功能:allocator模板定义出来的类对象并没有分配内存空间,只是定义了一个对象。此后需要调用allocate()函数来指定分配的元素个数
- 特点:allocate()函数分配的元素都是未初始化的,因此不能够直接使用。后面会介绍使用construct()函数来初始化
- 返回值:返回allocator类对象的首元素地址
allocator<string> alloc; //可以分配string的allocator对象,此时还不占用内存空间
auto const p = alloc.allocate(10); //分配n个未初始化的string
四、construct函数
- 功能:allocate()函数分配的内存元素都是未初始化的,因此不能够直接使用,需要调用该函数来对指定位置的元素进行初始化
- 特点:参数1位一个地址,参数2以及之后的参数是可变的(用来对参数1指定的位置进行初始化的元素)
allocator<string> alloc;
auto const p = alloc.allocate(10);
auto q=p; //q指向最后构造的元素之后的位置
//在q位置进行构造,然后指针再向后偏移一个元素的大小
alloc.construct(q++); //*q为空字符串
alloc.construct(q++,10,'c');//*q为10个c的字符串(cccccccccc)
alloc.construct(q++,"hi"); //*q为hi
五、destroy函数还未构造对象就直接使用是错误的:
cout<< *p <<endl; //正确,使用stirng的输出运算符 cout<< *q <<endl; //错误,q最后++指向一块未构造的内存
- 功能:当我们使用完对象之后,如果不再需要该对象,就可以调用该函数来销毁指定的元素
- 参数:为一个指定位置元素的地址
六、deallocate函数
- 在循环开始处,q指向最后一个构造的元素的下一个位置,我们将其传入destroy函数中,然后循环递减逐渐释放内存
while(q!=p) alloc.destroy(--q); //销毁指定位置的元素
- 功能:如果destroy函数销毁指定位置的元素之后,该位置不再使用,就可以调用该函数来释放该位置的内存空间
- 参数:参数1是要销毁的内存起始地址,参数2是要销毁的个数
- 注意:参数1的指针不能为空
七、拷贝和填充未初始化内存的算法
- 上面我们调用了destroy函数销毁了所有的元素,接下来我们调用deallocate函数将所有的元素内存释放
alloc.deallocate(p,10);
- 标准库为allocator类定义了两个伴随算法。可以在未初始化内存中创建对象
- 头文件:#include<memory>
uninitialized_copy函数返回递增后的目的位置迭代器
演示案例:
- 我们现在有一个int型的vector。然后我们创建一个2倍vector对象的动态内存,然后在动态内存的前半部分拷贝vector的对象。后半部分用指定的值填充
vector<int> vi = { 1,2,3,4,5 }; //分配一个vector数组 allocator<int> alloc; auto p=alloc.allocate(vi.size() * 2);//分配一个2倍vector大小的动态内存 auto q = uninitialized_copy(vi.begin(), vi.end(), p); //动态内存前半部分拷贝vector的内存,uninitialized_copy函数返回递增后的目的位置迭代器(alloc中间位置的地址) uninitialized_fill_n(q,vi.size(),666); //动态内存后半部分,全部使用666数组初始化