• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            Khan's Notebook GCC/GNU/Linux Delphi/Window Java/Anywhere

            路漫漫,長修遠,我們不能沒有錢
            隨筆 - 173, 文章 - 0, 評論 - 257, 引用 - 0
            數(shù)據(jù)加載中……

            STL Vector 的遍歷刪除.

            Vector 其實就類似動態(tài)數(shù)組. 事先分配好一定量的內(nèi)存. 當需要的內(nèi)存值大于某個閥值. 就重新申請內(nèi)存. 重新分配. 當小于某個閥值, 也會導致重新分配.(自動收縮部分, stl沒有明確規(guī)定, 有些庫實現(xiàn)了)

            正確: code1
                  vector<string> vecFiles;
                  vector<string>::iterator  it_pos;
                  //@todo 已下載文件過濾
                  for (it_pos = vecFiles.begin(); it_pos != vecFiles.end(); ) {
                    string strTmp = *it_pos;
                    if( objDownHis.checkHisList( strTmp.c_str() ) ){ //判斷是否已下載過, 已下載則從列表刪除
                      g_Log << TIME << "file:[" << *it_pos << "] found "<< END; //
                      vecFiles.erase(it_pos++);
                    }else
                      it_pos++;
                  }


            正確: code2
                  vector<string> vecFiles;
                  vector<string>::iterator  it_pos;
                  //@todo 已下載文件過濾
                  for (it_pos = vecFiles.begin(); it_pos != vecFiles.end(); ) { 
                    string strTmp = *it_pos;
                    if( objDownHis.checkHisList( strTmp.c_str() ) ){ //判斷是否已下載過, 已下載則從列表刪除
                      g_Log << TIME << "file:[" << *it_pos << "] found "<< END; //
                      it_pos = vecFiles.erase(it_pos);
                    }else
                      it_pos++;
                  }

            錯誤: code3
                  vector<string> vecFiles;
                  vector<string>::iterator  it_pos;
                  //@todo 已下載文件過濾
                  for (it_pos = vecFiles.begin(); it_pos != vecFiles.end(); it_pos++) { 
                    string strTmp = *it_pos;
                    if( objDownHis.checkHisList( strTmp.c_str() ) ){ //判斷是否已下載過, 已下載則從列表刪除
                      g_Log << TIME << "file:[" << *it_pos << "] found "<< END; //
                      vecFiles.erase(it_pos);
                    }
                  }


            code3 錯誤的原因為, vecFiles.erase(it_pos); 當前的it_pos已經(jīng)被刪除了, 再下一次循環(huán)的時候 it_pos++, 訪問非法內(nèi)存..

            然后回過頭來看code1, vecFiles.erase(it_pos++); 在當前的it_pos已經(jīng)被刪除的時候, it_pos已經(jīng)指向下一個位置了. 雖然這里邏輯上是錯誤的. 但是利用c語法的特性產(chǎn)生了一個正確的結(jié)果, 算是一個技巧. 不算是一門技術(shù).

            code2, it_pos = vecFiles.erase(it_pos); erase刪除的時候, 也返回了下一個指針的位置,我們將這個位置保留了, 所以這種做法也是正確的.


            另外一個移植性比較好的做法是remove_if 和一個仿函數(shù).

            仿函數(shù)可以是:
            struct check {
                check( Object * objDownHis ) : m_obj( objDownHis ) {}
                check( const check & c ) : m_obj( c.m_obj ) {}

                bool operator()(const string & s) const {
                   if ( m_obj->checkHisList( s.c_str() ) {
                        g_Log .........
                        return true;
                   }
                   return false;
                }
                Object * m_obj;
            };

            vecFiles.erase( std::remove_if( vecFile.begin(), vecFile.end(), check( &objDownHis ) );


            鳴謝p大, lancey, jackz 排名不分先后.. 全按交流時間順序...

            posted on 2009-12-08 13:29 Khan 閱讀(6204) 評論(5)  編輯 收藏 引用 所屬分類: GCC/G++跨平臺開發(fā)

            評論

            # re: STL Vector 的遍歷刪除.  回復  更多評論   

            >code3 錯誤的原因為, vecFiles.erase(it_pos); 當前的it_pos已經(jīng)被刪除
            >了, 再下一次循環(huán)的時候 it_pos++, 訪問非法內(nèi)存..

            >然后回過頭來看code1, vecFiles.erase(it_pos++); 在當前的it_pos已經(jīng)被
            >刪除的時候, it_pos已經(jīng)指向下一個位置了. 雖然這里邏輯上是錯誤的. 但是利
            >用c語法的特性產(chǎn)生了一個正確的結(jié)果, 算是一個技巧. 不算是一門技術(shù).

            我對這種的說法有不同看法:
            it_pos無所謂刪除不刪除,it_pos 的行為就像指針一樣,指針本身不會被刪除,被刪除的是指針指向的內(nèi)容。我想樓主可能對迭代器失效的理解有偏差(建議在網(wǎng)上查一查相關(guān)的資料再看看)
            我覺得,code1、2、3沒有什么本質(zhì)區(qū)別,都有可能產(chǎn)生迭代器失效的問題。
            一個原則:對vector只要做了刪除或是增加動作,就要示迭代器已經(jīng)無效,必須重新從vector對象獲取新的迭代器的值,而不能用臨時變量、后綴自增等方法……
            remove_if+erase的版本才是可讀性最好且沒什么問題的。

            個人愚見,請博主笑納……



            2009-12-08 18:43 | 唐風

            # re: STL Vector 的遍歷刪除.  回復  更多評論   

            傻傻的開發(fā)的
            2009-12-10 10:23 | 夢芭莎內(nèi)衣

            # re: STL Vector 的遍歷刪除.  回復  更多評論   

            code1的做法: 對非連續(xù)內(nèi)存容器是可行的 對連續(xù)內(nèi)存容器是不可取的
            code1中會出現(xiàn)漏刪 而不是內(nèi)存越界
            2009-12-10 17:45 | yisa

            # re: STL Vector 的遍歷刪除.  回復  更多評論   

            @yisa

            我用代碼驗證了下,的確是這樣:
            歡迎去我的空間討論交流 hi.baidu.com/bmrs
            1 /*
            2 DATE: 2010.6.25
            3 內(nèi)容:關(guān)于vector的遍歷刪除
            4 任何改變 vector 長度的操作都會使已存在的迭代器失效。例如,在調(diào)用 push_back 之后,就不能再信賴指向 vector 的迭代器的值了。
            5 */
            6 #include <iostream>
            7 #include <vector>
            8 #include <string>
            9 #include <cstring>
            10 using namespace std;
            11
            12 typedef vector<int> V;
            13 typedef vector<int>::iterator VIT;
            14 V v1;
            15
            16
            17 int main()
            18 {
            19 for(int i=0; i<10; ++i)
            20 v1.push_back(i);
            21
            22 VIT it = v1.begin();
            23 VIT it2;
            24 for(; it!=v1.end(); ++it)
            25 cout<<*it<<" ";
            26 cout<<endl<<v1.end()-v1.begin()<<endl; //vector容器的iterator是支持加減操作的,這在其他類型的迭代器中很少見
            27 VIT it0 = v1.begin()+1; // 1
            28 it2 = v1.begin()+3; // 3
            29 VIT it3 = it2+1; // 4
            30 cout<<"*it0="<<*it0<<" *it2="<<*it2<<" *it3="<<*it3<<endl;
            31
            32 for(it=v1.begin(); it!=v1.end(); ++it)
            33 {
            34 if(*it == 3)
            35 {
            36 cout<<"in for: before erase,*it="<<*it<<endl;
            37 VIT tmp = it;
            38 VIT r = v1.erase(it++);
            39 cout<<"in for: after erase,*tmp="<<*tmp<<endl;
            40 cout<<"in for: after it++ ,*it="<<*it<<endl;
            41 cout<<"in for: after erase,*r="<<*r<<endl;
            42 if(r == tmp)
            43 cout<<"A random access iterator pointing to the new location of the element that followed the last element erased by the function call, which is the vector end if the operation erased the last element in the sequence."<<endl;
            44 break;
            45 }
            46 }
            47
            48 cout<<"*it0="<<*it0<<" *it2="<<*it2<<" *it3="<<*it3<<endl;
            49 return 0;
            50 }
            2010-06-25 16:04 | glq

            # re: STL Vector 的遍歷刪除.  回復  更多評論   

            的說法是的范德薩阿士發(fā)送到發(fā)送到大夫阿士大夫士大夫士大夫撒大撒的
            2015-06-12 17:07 | 、開開
            久久久国产打桩机| 99热成人精品免费久久| 伊人久久大香线蕉av不卡| 欧美一区二区三区久久综合| 国内精品久久九九国产精品| 四虎影视久久久免费| 亚洲精品午夜国产VA久久成人| 久久综合九色综合精品| 亚洲性久久久影院| 四虎国产精品免费久久久| 久久99热这里只频精品6| 久久99国产精品一区二区| 色播久久人人爽人人爽人人片AV| 丁香五月网久久综合| 亚洲欧美国产精品专区久久| 久久亚洲欧美日本精品| 中文字幕日本人妻久久久免费| 国产激情久久久久影院| 久久久婷婷五月亚洲97号色| 久久精品无码一区二区三区日韩| 久久国产亚洲高清观看| 国产精品久久久久久久app| 99久久国产主播综合精品| 天堂久久天堂AV色综合| 亚洲国产成人久久综合碰| 久久久久亚洲AV无码去区首| 人人狠狠综合久久亚洲婷婷| 精品熟女少妇av免费久久| 亚洲AV日韩AV永久无码久久| 久久精品国产男包| 亚洲一级Av无码毛片久久精品| 久久精品视频91| 久久免费大片| 亚洲精品国精品久久99热| 伊人久久大香线蕉成人| 武侠古典久久婷婷狼人伊人| 中文字幕精品久久| 久久久无码精品亚洲日韩蜜臀浪潮| 久久久亚洲精品蜜桃臀| 日韩电影久久久被窝网| 久久久久亚洲AV片无码下载蜜桃 |