• <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>

            colorful

            zc qq:1337220912

             

            STL的remove函數(shù)和list的remove成員函數(shù)

            http://www.cnblogs.com/kinuxroot/archive/2013/01/25/stl_remove_problem.html

            今天看書剛剛看的,就記錄下來吧。這可能是老生常談了,權(quán)且作為一個警醒的例子吧。

            大家都知道STL有兩個非常重要的組成部分,容器和算法。

            算法就是一個個的函數(shù),通過迭代器和容器關(guān)聯(lián)在一起,完成一些工作。

            算法和容器的分離為程序設(shè)計提供了很大的靈活性,但是也帶來了一些負(fù)面效果,下面我講的這個問題就是一個例子。

            STL的算法里有一個remove函數(shù),而list自身也有一個remove函數(shù),功能都是一樣的,移除某一個元素,那我們應(yīng)該使用哪一個呢?

            看一下下面這段程序

            復(fù)制代碼
             1     list<int> numbers;  2   3     for ( int number = 0; number <= 6; number ++ ) {  4         numbers.push_front(number);  5         numbers.push_back(number);  6     }  7   8     copy(numbers.begin(), numbers.end(),  9             ostream_iterator<int>(cout, " ")); 10     cout << endl; 11  12     // remove algorithm will remove element but not erase the element from container 13     // it will return the logical desination of container 14     list<int>::iterator endOfNumbers = remove(numbers.begin(), numbers.end(), 3); 15  16     copy(numbers.begin(), numbers.end(), 17             ostream_iterator<int>(cout, " ")); 18     cout << endl;
            復(fù)制代碼

            輸出是什么呢?

            第一行肯定是6 5 4 3 2 1 0 0 1 2 3 4 5 6,那么第二行會輸出什么?

            如果是沒有仔細(xì)看過STL的人肯定會認(rèn)為remove(number.begin(), numbers.end(), 3)會移除所有值為3的元素。所以輸出是:6 5 4 2 1 0 0 1 2 4 5 6。

            但是,我們看一下它真正的輸出:

            6 5 4 2 1 0 0 1 2 4 5 6 5 6

            你可能會非常驚訝,為什么最后會多出5和6兩個數(shù)呢?

            我們來講一下remove算法的原理。

            remove算法工作時并不是直接把元素刪除,而是用后面的元素替代前面的元素,也即是說如果我對1234這個序列remove 2,返回的序列是 1344(3被復(fù)制到2的位置,4被復(fù)制到3的位置)。

            這樣上面的例子就好解釋了,那兩個3的元素并沒有被移除,而是用后面的元素覆蓋了前面的元素。多出的那兩個數(shù)沒有被移除掉而已。

            那么我們應(yīng)該如何真正完成移除呢?remove函數(shù)會返回一個迭代器,那個迭代器是這個序列的邏輯終點,也即是我代碼里的endOfNumbers,它指向倒數(shù)第二個5上。

            于是我們要利用list的erase函數(shù)完成元素移除

            numbers.erase(endOfNumbers, numbers.end());

            這樣我們就完成了我們的工作,稍稍有點曲折……

            其實我們可以把這兩步放在一起,比如如果我想接著移除所有值為2的元素

            numbers.erase(remove(numbers.begin(), numbers.end(), 2), numbers.end());

            這樣我們就可以一步到位了。

            但是這樣好么?

            不好。

            大家會發(fā)現(xiàn),remove函數(shù)的原理是復(fù)制而不是指針的移動(因為函數(shù)操縱的是迭代器,而C++的迭代器沒有定義刪除操作),這樣會帶來一個問題:我們使用list是因為它的修改的效率非常高,改變一下指針就可以了。而這里我們復(fù)制了元素,如果在vector中,可能還是高效的,因為vector無論如何都要復(fù)制,而對于list就不是如此了,會極度降低我們的效率。

            那我們怎么辦呢?

            答案是使用list自己的remove函數(shù)

            numbers.remove(1);

            我們可以這樣刪除所有值為1的元素。

            也即是說,如果要刪除list中的元素,我們應(yīng)該使用list的remove成員函數(shù),而不是remove算法!

            小結(jié)

            我們都知道,STL是一個效率、復(fù)用性、靈活性折衷的產(chǎn)物,其中效率至關(guān)重要,所以STL已經(jīng)禁止了一些效率低的操作(比如list的隨機(jī)訪問),而鼓勵你去使用其它的容器。

            但是,在算法中,為了靈活性,STL還是會犧牲一些東西,比如我們這個例子。

            個人覺得,STL作為C++標(biāo)準(zhǔn)庫的一個組成部分,特點和C++本身一模一樣,強(qiáng)大而復(fù)雜,有些地方難以理解,很多細(xì)節(jié)需要學(xué)習(xí)注意,我們要學(xué)會避免陷入某些陷阱之中,比如這個例子就是一個效率陷阱。

            其它更多的陷阱是錯誤處理方面的,STL本身并沒有規(guī)定過多的錯誤處理,大部分的錯誤處理都交給了我們,理由很簡單:性能至上,如果一個東西自身沒有錯誤檢查,我們可以包裝一個帶錯誤檢查的類;但是如果這個東西自身就帶了錯誤檢查,那么我們就沒有任何方法提升它的效率了。這也是很多C和C++庫的設(shè)計原則。

            所以,很多時候,需要我們深入細(xì)節(jié),然后再決定到底怎么做。因為C++就是如此:有很多路可以走,需要我們自己選擇最好的一條路。

            分類: C++

            posted on 2015-10-14 15:50 多彩人生 閱讀(908) 評論(1)  編輯 收藏 引用 所屬分類: boost

            評論

            # re: STL的remove函數(shù)和list的remove成員函數(shù)[未登錄] 2015-10-14 17:27 chipset

            remove函數(shù)并不是真正刪除,而是取代,然后調(diào)析構(gòu),built-in類型沒有析構(gòu)函數(shù)結(jié)果就發(fā)現(xiàn)只是向前移動了一下,僅覆蓋而已。
            復(fù)制元素并非就一定不高效,對于built-in類型,復(fù)制比修改指針高效,畢竟程序設(shè)計里小對象比大對象常見的多。再說了,大對象哪里有動不動就拷貝的,那是設(shè)計失誤。
            vector的刪除和插入都建議在尾進(jìn)行,否則效率低下,因此就沒有.pop_front這種貨。  回復(fù)  更多評論   

            導(dǎo)航

            統(tǒng)計

            常用鏈接

            留言簿(3)

            隨筆分類

            隨筆檔案

            搜索

            最新評論

            閱讀排行榜

            評論排行榜

            久久国产精品免费一区| 久久99精品久久久大学生| 久久精品嫩草影院| 久久国产高清字幕中文| 久久国产视屏| 伊人久久精品无码av一区| 91精品国产综合久久婷婷| 66精品综合久久久久久久| 国产成人无码精品久久久性色| 久久国产一区二区| 无码人妻久久一区二区三区蜜桃| 人妻无码αv中文字幕久久| 亚洲国产精品久久66| 一本色道久久综合亚洲精品| 久久精品亚洲男人的天堂| 久久久久亚洲av无码专区喷水| 久久影院亚洲一区| 久久99国产精品久久| 国产A三级久久精品| 亚洲精品美女久久久久99小说 | 久久99精品国产麻豆宅宅| 久久久久国产| 国产精品99久久不卡| 国产成人精品久久免费动漫| 综合网日日天干夜夜久久| 少妇久久久久久被弄到高潮| 亚洲天堂久久精品| 国产亚洲综合久久系列| 久久婷婷国产综合精品| 久久久久久精品免费看SSS| 伊人久久无码精品中文字幕| 精品久久久久国产免费| 久久激情五月丁香伊人| 国产99久久久久久免费看| 99久久99久久精品国产| 亚洲午夜精品久久久久久人妖| 久久九九青青国产精品| 日本久久久久久中文字幕| 久久99中文字幕久久| 91精品国产91久久久久久蜜臀| 久久被窝电影亚洲爽爽爽|