现在的位置: 首页 > 综合 > 正文

玩玩vector

2013年04月04日 ⁄ 综合 ⁄ 共 3204字 ⁄ 字号 评论关闭

转自:http://blog.csdn.net/norains/archive/2008/05/10/2431642.aspx

 

//========================================================================
//TITLE:
//    玩玩vector
//AUTHOR:
//    norains
//DATE:
//    Saturday  10-May-2008
//Environment:
//    VS2005 + MIPS-SDK
//========================================================================

    本文不是讨论为什么要用vector替代数组,或是为什么一定要使用vector,而是在如何用vector在一些场合起到有意思的运用。本文所讨论的方式,并不是建立于推荐的原则,而仅仅是展示vector的有趣用法。在实际中是否使用,可各自掌握。
   
    1.内存动态分配
   
    最常常用的场合,vector其实也是为此而诞生的。举个很简单的例子:
   
    普通代码:
    #define NEW_SIZE  10
    int *pArr = new int[NEW_SIZE];
    ...
    delete []pArr;
   
    vector替代代码:
    std::vector<int> vct;
    vct.resize(NEW_SIZE);
   
    好处不言而喻,采用new分配内存的话,还需要调用delete来负责释放;而如果采用vector,那么,只要分配就好。释放?不管,就让编译器操心吧!
   
   
    2.存储字符串
   
    既然数组能存储字符串,那么vector自然也不甘落后咯。
   
    普通代码:
    WCHAR szPath[MAX_PATH];
    wcscpy(szPath,L"path");
   
    vector替代代码:
    std::vector<WCHAR> vctPath(MAX_PATH);
    wcscpy(&vctPath[0],L"path");
   
    在这里我们需要注意一点,标准C++中规定,vector的数据保存是必须在一段连续的内存中,所以我们在函数中可以使用&vctPath[0]的方式。注意,这里还有一个[0]下标,因为如果没有该下标,而仅仅是&vctPath,那么该地址只是对象的起始地址,而不是数据存储的起始地址。对于wcscpy函数来说,它的目标地址必须为一块连续的数据存储内存,而&vctPath[0]刚好符合。
   
    由此我们可以得出一个结论,凡是需要传递数组起始地址的场合,如果使用vector,那么都可以采用&vector[0]的方式替代。
   
   
    3.存储内存数据
   
    其实这部份内容和第2点差不多,vector既然能存储字符串,那么铁定也能存储内存的数据。
   
    普通代码:
    #define MEM_SIZE  20
    BYTE * pMem = malloc(MEM_SIZE);
    ...
    free(pMem);
   
    vector替代代码:
    std::vector<BYTE> vct;
    vct.resize(MEM_SIZE);
   
    在使用内存处理函数时只要采用和第二点相同的方式即可:
    memcpy(&vct[0],pBuf,20);
   
    不过本节的重点不在于如何存储内存数据,因为这可以通过第1、2点可以推断出来,而是想说明另外一个问题,采用vector可能可以起到简化函数行参的作用。
   
    举个例子,我们实际想写一个函数,需要转换pSource指向的内存数据,那么我们的这个函数至少需要两个参数,分别是指向分配的内存,以及该内存区域的大小:
    void Convert(BYTE * pBuf, ULONG ulSize)
    {
      for(int i = 0; i < ulSize; i ++)
      {
      ...
      }
    }
   
    但如果是用vector作为形参,由于vector可以调用size()函数获取长度,所以可以减少一个形参个数:
    void Convert(std::vector<BYTE> &vect)
    {
     for(std::vector<BYTE>::size_type i = 0; i < vect.size(); i ++)
       {
       ...
       }
    }
   
   
    4.vector的一个应用示例
   
    在文章的最后,举一个vector可以简化设计的例子。
   
    如果我们需要设计这么一个函数,输入班级的序号,然后返回班里每个人的成绩。
   
    因为需要存储每个人的成绩,所以采用数组来存储应该是一个很合理的选择。又因为每个班级的人数不一致,所以我们必须采用动态分配数组的方式:
   
    int * GetScore(int iIndexClass,int *pLen)
    {
      ...
     
      int *pNew = new int[iAmount_cls_1];
      *pLen = iAmount_cls_1;
      ...
     
      return pNew;
    }
   
    这会引发一个问题,首先我们需要增加一个形参,用来指示该数组的长度。当然,这还是其次,最重要的是,因为内存是动态分配的,需要手工释放。问题就出来了,内存的分配是函数内部分配,而释放需要调用者手工释放!万一调用者忘记释放了呢?最好的结果无非是内存慢慢被侵蚀,然后出现异常。而调用者如果记得释放呢?是不是就没问题了呢?错!在例子中,调用者应该是需要调用delete来释放内存;而如果万一某一天,GetScore函数的编写者不采用new方式,而是malloc,那么调用者调用delete释放内存会出现什么结果?喔,我也不知道,因为C++中未定义。
   
    似乎使用数组让我们走入了个两难的境地。那么,如果使用vector呢?
   
    函数如下:
       
    std::vector<int> GetScore(int iIndexClass)
    {
      ...
    
     vector<int> vct(iAmount_cls_1);
   
      ...
     
      return vct;
    }
   
    使用就非常简单咯:
    vector<int> vctScore;
    vctScore = GetScore(1);
   
    不用手工释放内存,不用增加多余的指示长度参数(因为可以调用vctScore.size()来获取),一切都那么简单,一切都那么美好,难道不是么?

发表于 @ 2008年05月10日 23:52:23|评论(2

)

新一篇: AU1200 GPIO的使用 | 旧一篇: 喘气

hkooyu 发表于2008年6月1日 23:06:36  IP:举报
std::vector<int> GetScore(int iIndexClass)
{
...

vector<int> vct(iAmount_cls_1);

...

return vct;
}

vct会不会被析构?

norains 发表于2008年6月2日 9:24:12  IP:举报
Re hkooyu: 你可以将这个函数类比于:int GetSCore(int iIndexClass){... int i;...return i;} 这样应该能解决你的疑惑吧? :-)
flushtime 发表于2008年7月5日 9:36:57  IP:202.113.19.*举报
vct会被析构,但析构前会得到vct的一个拷贝。

抱歉!评论已关闭.