vector&String的适当容量

        STL vector 比较神奇的地方,就是它会自动的扩展自己的容量。而这些是在 C/C++ 的低级数据结构——数组里面是办不到的。

 

合适的扩张:

         譬如,在 C++ 中,有如下的代码:

         const int kSize = 10;

         int ar[kSize];

 

         数组 ar 的大小是在编译期间完成,它的内容是存在内存中的栈里面。顺便提一下,在 c c++ 中,由编译器分配的内存是分配在栈( Stack )里面,而由程序员分配管理的内存是在堆( heap )里面。

 

         数组就是相同类型的一种集合的其中一种表现形式。它具有快速,简单的特点。但是想进一步的扩展是比较困难的。譬如我想把上面的数组的大小改为 11 ,那明显是很难办到的。 STL 中的 vector 可以帮你解决这个问题。

 

         譬如,在 C++ 中的下面的代码:

         const  int  kSize = 10;

         vector<int > iv;

         for (int i = 0; i < kSize; ++i)  {

         iv.push_back(i);

}

那么容器 iv 中有是kSize个元素,同时,这个时候,我想在这个容器加进去一个元素,是非常方便的。譬如,我想加一个 int a = 100 的数进来, iv.push_back(a); 就行了。

 

 

是的,上面的代码确实是比较好,比数组灵活很多。但绝对不是最好的。这涉及到 vector 的内存分配机制。

先看 vector 的几个成员函数:

size ():这个函数是获得 vector 容器有多少个元素。

capacity ():这个函数获得 vector 容器还能在内存中可以容纳多少元素。(不会导致内存重新分配,下面会讲解这个)。

resize () : 强行把 vector 的元素个数扩展或者是减少到所指定的元素。

reserve ():把容器的容量置为所指定的元素。

 

vector 的内存分配机制:当向其插进元素,而超过它的容量的时候,它会以一种哲学的方式配置自己的容量。

什么是哲学的方式呢?按照上面的代码,当你想 iv 容器插入一个元素的时候,它可能分配 1 个大小的内存,也可能分配 2 个大小的内存,也可能分配 3 个大小的内存……在 GNU g++ 中,它会以原来 2 倍的内存大小增加(请参考《 STL 源码剖析》)

同时,会进行一次的内存“搬移”,譬如假设上面已经有 5 个元素,他的容量也为 5 ,再向 vector 插入一个元素,这样会发生以下的动作:

1、  它必须重新分配适当的新的内存空间。

2、  把原来的数据“ copy ”过到新的空间,再插入一个元素。

3、  销毁原来的数据。

这是一个非常耗时的过程。

然而这个问题是怎么解决,不至于有这么多好耗时的动作呢? reserve ()成员函数。把上面的代码改为:

         const  int  kSize = 10;

         vector<int > iv;

         iv.reserve(kSize);

         for (int i = 0; i < kSize; ++i)  {

         iv.push_back(i);

 }

只是在 vector 在分配内存的机制上面,预先保留,就可以减少:

1、  内存重新分配。

2、  内存“数据搬移”

3、  销毁原来的数据

三个动作。

 

合适的收缩:

         问题的引进:现在容器 vector 存贮着 100000 人的数据,而我们只是根据某种质量,把关注点放在前十位。譬如:在这些人中,选出 10 个是长得最高的(只是需要简单的 sort 就行),其他的 99990 人都不关心,所以想从内存中删除。

代码 :

class Person {

         ……

}

vector<Person> ip;

……

 

在删除 vector 的元素,一般采用 erase-remove 的方法,但是这个方法只能是减少元素,并不能减少容器本身所占用的内存空间。咋办?比你想象的更加简单,只是需要一句话:

vector<Person>(ip).swap(ip);

 

当你打印出 ip.capacity() 的前后的值,就发现完全是不同的。

 

 

string 可以采用和 vector 基本相同的方式来管理合适的内存,不会导致内存的多次分配造成的无谓的消耗,也不会导致内存的过大,导致内存的浪费。

 

在合适的收缩内存这一点上,不一定采用 vector ,或者是 map 处理更加好, map 是采用红黑二叉树的方式写成,可以按照某种质量自动排序,获取前 10 位。

 

请参考《 C++ primer 》,《 Effective C++ 》,《 Effective STL 》,《 STL 源码剖析》

 

后记:

想了好久,写什么为第一篇技术文章,还是选择了 STL ,是以前曾经认真的学过和认为非常了不起的东西。由于工作的关系,可能准备写 Java ,设计模式,和 Android 的。写得不好,不清晰,错误的,请大家指出。谢谢!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值