摘要:本文描述的是一种很常见的情况:当你在某个缓存中存储数据时,常常需要在运行时调整该缓存的大小,以便能容纳更多的数据。本文将讨论如何使用 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::copy

int reallocate(int* &p, int& size)
{
 size*=2; // double the array''s size with each reallocation
 int * temp = new int[size];
 std::copy(p, p+(size/2), temp);
 delete [] p; // release original, smaller buffer
 p=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: "<<vi[n]<<endl;
}

  第二步:优化

  在大多数情况下,你应该让 vector 自动管理自己的内存,就像我们在上面程序中所做的那样。但是,在注重时间的任务中,改写默认的分配方案也是很有用的。假设我们预先知道 ISBNs 的数量至少有 2000。那么就可以在对象构造期间指出容量,以便 vector 具有至少 2000 个元素的容量:

vector <int> vi(2000); // 初始容量为 2000 个元素

  除此之外,我们还可以调用 resize() 成员函数:

vi.resize(2000);// 建立不小于 2000 个元素的空间

  这样,便避免了中间的再分配,从而提高了效率。

C++中用vectors改进内存的再分配相关推荐

  1. 在vc2008中用_crtBreakAlloc调试内存泄漏

    在vc2008中用_crtBreakAlloc调试内存泄漏 2012-07-27 16:58:25 分类: C/C++ 这两天调一个程序,发现每次退出都有内存泄漏,在此总结一个调试内存泄漏的好方法. ...

  2. Linux 内核中用 GFP_ATOMIC 申请内存究竟意味着什么?

    作者 | 宋宝华  责编 | 张文 头图 | CSDN 下载自东方 IC 来源 | Linux阅码场(ID:LinuxDev) 本文目的:本文补充校正一些 Linux 内核开发者关于 GFP_ATOM ...

  3. 宋宝华:Linux内核中用GFP_ATOMIC申请内存究竟意味着什么?

    本文目的 本文补充校正一些Linux内核开发者关于GFP_ATOMIC的认知不完整的地方,阐述GFP_ATOMIC与free内存watermark的关系,并明确什么时候应该用GFP_ATOMIC申请内 ...

  4. java组合框单位换算_Visual C++开发实战1200例(第Ⅰ卷)

    第1篇 编程基础 第1章 开发环境 1.1 工程创建 实例001 如何创建基于对话框的MFC工程 实例002 如何创建基于文档视图的MFC工程 实例003 打开已存在的工程 实例004 怎样查找工程中 ...

  5. 计算机硬件知识:内存

    作为现代计算机的基础,冯·诺依曼体系结构的计算机主要由运算器.控制器.存储器和输入输出设备组成,其中存储器在现代计算机里面指的就是内存和硬盘.内存的主要作用就是处理器与外部之间进行通讯的时候,作为一个 ...

  6. 垃圾回收器的基本原理是什么?垃圾回收器可以马上回收内存吗?有什么办法主动通知虚拟机进行垃圾回收?...

    一.垃圾回收器的基本原理是什么?垃圾回收器可以马上回收内存吗?有什么办法主动通知虚拟机进行垃圾回收?   1.对于GC来说,当程序员创建对象时,GC就开始监控这个对象的地址.大小以及使用情况. 通常, ...

  7. 智能指针和内存管理小结

    ·概述: 主要是两个库:smart_ptr库和pool库. smart_ptr库主要解决的问题是指针的内存泄漏和垃圾回收问题:pool则是解决内存分配问题. 感觉还是smart_ptr库比较好用一些, ...

  8. Linux内存管理之高端内存映射

    一:引子 我们在前面分析过,在linux内存管理中,内核使用3G->4G的地址空间,总共1G的大小.而且有一部份用来做非连续空间的物理映射(vmalloc).除掉这部份空间之外,只留下896M大 ...

  9. 操作系统第三章-内存管理

    写在前面:本文参考王道论坛的 操作系统考研复习指导单科书 下面的流程图很重要. 加入快表的基本分页 加入快表的二级页表!! 虚拟存储器:请求分页的流程图. 文章目录 第三章 内存管理 3.1 内存管理 ...

最新文章

  1. 在WINDOWS2008 Server 中创建NFS服务器,使用LINUX的MOUNT命令去加载网络盘
  2. OpenCV黑白图像增强——灰度级切片
  3. 软件需求包括3个不同的层次 - 业务需求、用户需求和功能需求
  4. K8s容器集群管理系统
  5. php中文歌词,html如何制作滚动歌词
  6. ruby 将字符串转为数组_Ruby程序将数组打印为字符串
  7. java中选择结构有哪些_Java中的选择结构
  8. android 选择多选图片
  9. uni-app 行内样式动态背景图 :style 绑定
  10. [C++面试题]之冒泡排序
  11. php 日志库,这可能是php世界中最好的日志库——monolog
  12. python二元函数图像在线绘制_numpy,matplotlib
  13. AS连接MUMU模拟器
  14. 判定通视的计算法公式_水准仪的后视和前视怎么区别?计算公式是什么?
  15. 【JS从入门到精通】09-数组
  16. python从入门到实践16章答案
  17. [MySQL 源码] Innodb Pessimistic Insert流程
  18. 新手做网页设计?这9款经典网页布局设计了解下
  19. (项目)审计系统(堡垒机)
  20. 织梦网站转移主机服务器教程

热门文章

  1. 第四部分 Calendar使用示例
  2. 潮流玩具行业趋势与洞察白皮书
  3. 服务业小店店主生活和工作洞察报告
  4. 专题导读:大数据支撑的智能应用
  5. 【2016年第5期】数据科学人才的需求与培养
  6. React组件-事件、状态和生命周期
  7. selenium:断言
  8. 《测试驱动数据库开发》—第1章1.2节谁是目标读者
  9. python 反射实体,动态应用
  10. 为html.EditorFor添加样式