a我考网

 找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

查看: 127|回复: 2

[C++] 2011年计算机等级考试二级C++辅导实例编程(19)

[复制链接]
发表于 2012-7-31 21:56:58 | 显示全部楼层 |阅读模式
 C++中用vectors改进内存的再分配  摘要:本文描述的是一种很常见的情况:当你在某个缓存中存储数据时,常常需要在运行时调整该缓存的大小,以便能容纳更多的数据。本文将讨论如何使用 STL 的 vector 进行内存的再分配。
, Z; V2 }2 l8 ~  这里描述的是一种很常见的情况:当你在某个缓存中存储数据时,常常需要在运行时调整该缓存的大小,以便能容纳更多的数据。传统的内存再分配技术非常繁琐,而且容易出错:在 C 语言中,一般都是每次在需要扩充缓存的时候调用 realloc()。在 C++ 中情况更糟,你甚至无法在函数中为 new 操作分配的数组重新申请内存。你不仅要自己做分配处理,而且还必须把原来缓存中的数据拷贝到新的目的缓存,然后释放先前数组的缓存。本文将针对这个问题提供一个安全、简易并且是自动化的 C++ 内存再分配技术——即使用 STL 的 vector。
) |9 C+ v( G/ U) j( z& f  用 STL vector 对象取代内建的数组来保存获取的数据,既安全又简单,并且是自动化的。. p! s# t1 h1 y" d+ k" J
  进一步的问题分析- a7 I: G- V; B! {
  在提出解决方案之前,我先给出一个具体的例子来说明 C++ 重新分配内存的弊病和复杂性。假设你有一个编目应用程序,它读取用户输入的 ISBNs,然后将之插入一个数组,直到用户输入 0 为止。如果用户插入的数据多于数组的容量,那么你必须相应地增加它的大小:, M% o2 G- l9 f8 a; V; z
  #include
9 I: O, I, j( V, x4 Y0 Q% N  using namespace std;
  x3 ^) c* m" S( x  int main()  O& t4 U" }1 l& F* f. b& F  t
  {' t+ k8 o3 X' s8 _
  int size=2; // 初始化数组大小;在运行时调整。
5 ?  W1 a$ ^4 ~/ F  int *p = new int[size];
$ C, s; T+ S- N  int isbn;( p6 o4 |% }- S2 f
  for(int n=0; ;++n); w6 D2 x& x: w
  {% m* M3 X+ I- y$ ^
  cout>isbn;
回复

使用道具 举报

 楼主| 发表于 2012-7-31 21:56:59 | 显示全部楼层

2011年计算机等级考试二级C++辅导实例编程(19)

 if (isbn==0)  break;
: B. \, |1 c1 b: m- U( U6 q  if (n==size) // 数组是否到达上限?
& ~) `- N5 w6 \8 {  reallocate(p, size);' F0 p" G+ Q+ S0 ]* z
  p[n]=isbn; // 将元素插入扩容的数组
9 s( L7 l. m5 o5 g. S  }
  _$ j( A3 C& i$ @$ h, ]  delete [] p; // 不要忘了这一步!9 s$ A# U* A/ l0 C: h4 p
  }( Z* A' M, c" R: S* L, S# b
  注意上述这个向数组插入数据的过程是多么的繁琐。每次反复,循环都要检查缓存是否达到上限。如果是,则程序调用用户定义的函数 reallocate(),该函数实现如下:" b* b' S0 X- \1 J0 m
  #include // for std::copy3 D& a" Y! I+ ~; p( R4 ]
  int reallocate(int* &p, int& size)
! y8 v7 W0 A8 ]* }  {
# d- Y/ I& s5 \! J9 k8 U6 b2 t/ O  size*=2; // double the array''s size with each reallocation
, j" e' O* N' ]4 r3 Q  int * temp = new int[size];7 D6 q3 X. }" _/ a% `6 @% [
  std::copy(p, p+(size/2), temp);# W) U  ]1 l& |. i
  delete [] p; // release original, smaller buffer
  o  N" I! U4 |  p=temp; // reassign p to the newly allocated buffer
) A( n( H: i0 a7 p) ~: }7 ]( l/ M  }
, u6 c" k! I8 Z  v0 t  reallocate() 使用 STL std::copy() 算法对缓存进行合理的扩充——每次扩充都放大一倍。这种方法可以避免预先分配过多的内存,从量上减少需要重新分配的内存。这个技术需要得到充分的测试和调试,当初学者实现时尤其如此。此外,reallocate() 并不通用,它只能处理整型数组的情形。对于其它数据类型,它无能为力,你必须定义该函数额外的版本或将它模板化。幸运的是,有一个更巧妙的办法来实现。
( Q+ `( c: k  i) p( C9 R  创建和优化 vector
1 W0 S$ X  \, O0 J  每一个 STL 容器都具备一个分配器(allocator),它是一个内建的内存管理器,能自动按需要重新分配容器的存储空间。因此,上面的程序可以得到大大简化,并摆脱 reallocator 函数。: c. a" ?, f3 W% S9 p
  第一步:创建 vector' ]" `/ D+ K6 B3 ^4 w3 @1 p* N
  用 vector 对象取代内建的数组来保存获取的数据。main() 中的循环读取 ISBN,检查它是否为 0,如果不为 0 ,则通过调用 push_back() 成员函数将值插入. G* ]8 k$ N; l4 B
  vector: #include
/ F) e' S( f8 f  #include
' o7 S3 n! f# C  using namespace std;
' h! r) b' C, z8 J. T2 d  int main()
$ p" r) V) }/ J0 z/ Q* m  {
3 C( j6 g$ U: \; O  vector vi;5 r6 |% V7 j, ^; _! N
  int isbn;
1 F: v! \$ ]/ p% f6 {  while(true)
1 ^* ^* }+ K2 s' L0 i+ \2 ~  {5 ?; E/ l) B' X) Q
  cout > isbn;7 O% L  ]2 y7 ?0 ?& X4 r
  if (isbn==0)
* N/ j3 u6 r) |& b( J; R, [  break;
9 y3 o8 o* a- d" B  vi.push_back(isbn); // insert element into vector
* J/ x8 j* i( R( Q  }
& i" ?5 m5 Q. q& Q9 n2 w% T  }
回复 支持 反对

使用道具 举报

 楼主| 发表于 2012-7-31 21:57:00 | 显示全部楼层

2011年计算机等级考试二级C++辅导实例编程(19)

 在 vector 对象构造期间,它先分配一个由其实现定义的默认的缓存大小。一般 vector 分配的数据存储初始空间是 64-256 存储槽(slots)。当 vector 感觉存储空间不够时,它会自动重新分配更多的内存。实际上,只要你愿意,你可以调用 push_back() 任何多次,甚至都不用知道一次又一次的分配是在哪里发生的。  为了存取 vector 元素,使用重载的 [] 操作符。下列循环在屏幕上显示所有 vector 元素:5 p. G6 o5 ?& |, ^! y

/ _# v/ J5 }  B7 F0 o% d  for (int n=0; n
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|Woexam.Com ( 湘ICP备18023104号 )

GMT+8, 2024-5-18 15:05 , Processed in 0.155920 second(s), 25 queries .

Powered by Discuz! X3.4 Licensed

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表