用 vectors 改进内存的再分配

2016-01-29 12:28 7 1 收藏

用 vectors 改进内存的再分配,用 vectors 改进内存的再分配

【 tulaoshi.com - C语言心得技巧 】

用 vectors 改进内存的再分配

作者:Danny Kalev
编译:MTT 工作室

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com)

原文出处:Improving Memory Reallocation with Vectors

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com)
摘要:本文描述的是一种很常见的情况:当你在某个缓存中存储数据时,常常需要在运行时调整该缓存的大小,以便能容纳更多的数据。本文将讨论如何使用 STL 的 vector 进行内存的再分配。

  这里描述的是一种很常见的情况:当你在某个缓存中存储数据时,常常需要在运行时调整该缓存的大小,以便能容纳更多的数据。传统的内存再分配技术非常繁琐,而且容易出错:在 C 语言中,一般都是每次在需要扩充缓存的时候调用 realloc()。在 C++ 中情况更糟,你甚至无法在函数中为 new 操作分配的数组重新申请内存。你不仅要自己做分配处理,而且还必须把原来缓存中的数据拷贝到新的目的缓存,然后释放先前数组的缓存。本文将针对这个问题提供一个安全、简易并且是自动化的 C++ 内存再分配技术——即使用 STL 的 vector。

用 STL vector 对象取代内建的数组来保存获取的数据,既安全又简单,并且是自动化的。
 
进一步的问题分析
  在提出解决方案之前,我先给出一个具体的例子来说明 C++ 重新分配内存的弊病和复杂性。假设你有一个编目应用程序,它读取用户输入的 ISBNs,然后将之插入一个数组,直到用户输入 0 为止。如果用户插入的数据多于数组的容量,那么你必须相应地增加它的大小:
#include <iostream>using namespace std;int main(){int size=2; // 初始化数组大小;在运行时调整。int *p = new int[size];int isbn;for(int n=0; ;++n){cout<< "enter an ISBN; press 0 to stop ";cin>>isbn;if (isbn==0)break;if (n==size) // 数组是否到达上限?reallocate(p, size);p[n]=isbn; // 将元素插入扩容的数组}delete [] p; // 不要忘了这一步!}

  注意上述这个向数组插入数据的过程是多么的繁琐。每次反复,循环都要检查缓存是否达到上限。如果是,则程序调用用户定义的函数 reallocate(),该函数实现如下:

#include <algorithm> // for std::copyint reallocate(int* &p, int& size){size*=2; // double the array''s size with each reallocationint * temp = new int[size];std::copy(p, p+(size/2), temp);delete [] p; // release original, smaller bufferp=temp; // reassign p to the newly allocated buffer}    
  reallocate() 使用 STL std::copy() 算法对缓存进行合理的扩充——每次扩充都放大一倍。这种方法可以避免预先分配过多的内存,从量上减少需要重新分配的内存。这个技术需要得到充分的测试和调试,当初学者实现时尤其如此。此外,reallocate() 并不通用,它只能处理整型数组的情形。对于其它数据类型,它无能为力,你必须定义该函数额外的版本或将它模板化。幸运的是,有一个更巧妙的办法来实现。

创建和优化 vector
  每一个 STL 容器都具备一个分配器(allocator),它是一个内建的内存管理器,能自动按需要重新分配容器的存储空间。因此,上面的程序可以得到大大简化,并摆脱 reallocator 函数。

第一步:创建 vector
  用 vector 对象取代内建的数组来保存获取的数据。main() 中的循环读取 ISBN,检查它是否为 0,如果不为 0 ,则通过调用 push_back() 成员函数将值插入 vector:
#include <iostream>#include <vector>using namespace std;int main(){vector <int> vi;int isbn;while(true){cout << "enter an ISBN; press 0 to stop ";cin >> isbn;if (isbn==0)break;vi.push_back(isbn); // insert element into vector}}    
  在 vector 对象构造期间,它先分配一个由其实现定义的默认的缓存大小。一般 vector 分配的数据存储初始空间是 64-256 存储槽(slots)。当 vector 感觉存储空间不够时,它会自动重新分配更多的内存。实际上,只要你愿意,你可以调用 push_back() 任何多次,甚至都不用知道一次又一次的分配是在哪里发生的。

为了存取 vector 元素,使用重载的 [] 操作符。下列循环在屏幕上显示所有 vector 元素:
for (int n=0; n<vi.size(); ++n){    cout<<"ISBN: "<
                        

来源:http://www.tulaoshi.com/n/20160129/1486251.html

延伸阅读
根据sgi 的STL源码的二级分配算法改写的内存池分配程序,只要稍微修改就可以实现共享内存方式治理,使用C++标准库容器中的map,set,multimap,multiset测试通过,vector测试通不过,原因是在内存回收的时候考虑的比较简单,vector每次分配内存个数不固定,回收也不固定,这样的话,程序还需要继续完善。 内存池治理程序源码如下:?XML:name...
如果要给二维数组(m*n)分配空间,代码可以写成下面: 代码如下: char **a, i; // 先分配m个指针单元,注意是指针单元 // 所以每个单元的大小是sizeof(char *) a = (char **) malloc(m * sizeof(char * )); // 再分配n个字符单元, // 上面的m个指针单元指向这n个字符单元首地址 for(i = 0; i m; i++) a[i] = (char * )malloc(n * siz...
标签: SQLServer
  SQL服务器内存有两种基本管理方法:动态分配和静态分配 控制程序可使用的内存数量。动态分配允许管理员声明一块内存的大小;考虑到它的实际使用,SQL服务器可以分配给其需要占用的内存的最大值,并且(理论上)在没有使用内存的情况下将其释放。静态分配则是创建一块固定的内存空间,提供给SQL Server使用——不再进行分配。 ...
假设我们要开发一个String类,它可以方便地处理字符串数据。我们可以在类中声明一个数组,考虑到有时候字符串极长,我们可以把数组大小设为200,但一般的情况下又不需要这么多的空间,这样是浪费了内存。对了,我们可以使用new操作符,这样是十分灵活的,但在类中就会出现许多意想不到的问题,本文就是针对这一现象而写的。现在,我们先来开发一...
标签: 理财 投资
告诉大家信托收入如何分配,给有志于进入信托投资领域的人一些参考经验。希望能够帮助到大家 信托收入如何分配 信托收入如何分配标准和分配方案由信托公司根据《信托合同》的约定进行核算和制定,保管人有权进行复核。 具体来说,信托公司负责按照《信托合同》的约定计算信托收入和出具信托收入支付表,并分别在信托收入分配日前发...

经验教程

899

收藏

79
微博分享 QQ分享 QQ空间 手机页面 收藏网站 回到头部