玩玩vector

轉自: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 <script type="text/javascript"></script> )

新一篇: AU1200 GPIO的使用 | 舊一篇: 喘氣

<script type="text/javascript"></script> <script src="http://hi.images.csdn.net/js/blog/feedback.js" type="text/javascript"></script>
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的一個拷貝。
發佈了20 篇原創文章 · 獲贊 2 · 訪問量 43萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章