• <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>
            Impossible is nothing  
              愛過知情重醉過知酒濃   花開花謝終是空   緣份不停留像春風來又走   女人如花花似夢
            公告
            日歷
            <2025年6月>
            25262728293031
            1234567
            891011121314
            15161718192021
            22232425262728
            293012345
            統計
            • 隨筆 - 8
            • 文章 - 91
            • 評論 - 16
            • 引用 - 0

            導航

            常用鏈接

            留言簿(4)

            隨筆分類(4)

            隨筆檔案(8)

            文章分類(77)

            文章檔案(91)

            相冊

            搜索

            •  

            最新評論

            閱讀排行榜

            評論排行榜

             

            從 STL 出現到現在已經這么多年了,泛型算法是它的重要組成,也是其中最“看起來很美”的東西之一。然而在真實的程序設計中,它往往成為程序員的心頭一痛,因為一旦要用 for_each ,accumulate 之類的算法做一些稍微復雜一點的事情,你就會發現自己一個頭變成兩個大。

            從 STL 出現到現在已經這么多年了,泛型算法是它的重要組成,也是其中最“看起來很美”的東西之一。然而在真實的程序設計中,它往往成為程序員的心頭一痛,因為一旦要用 for_each ,accumulate 之類的算法做一些稍微復雜一點的事情,你就會發現自己一個頭變成兩個大。即便是有了 boost::bind 和 boost.lambda 的幫助,事情也仍然是撲朔迷離,求助于 comp.lang.c++ 雖然有用,但是又何嘗不是一種無奈。好了,現在我開始收集一些來自 comp.lang.c++(.moderated) 的解答,希望日后對自己和他人有用。

            =================================================================================

            預備問題(算是第0個問題吧):如何對一個 STL 容器內的所有元素做某件事情?

            這取決于你要做什么,以及容器是什么。如果是 vector, list 這樣的容器,而你要把它們全部 cout 出來,當前的標準 STL 解法是這樣的:

            #include <iostream>
            #include <algorithm>
            #include <vector>
            #include <iterator>
            #include <string>

            int main()
            {
            ? std::vector<std::string> vect;
            ? vect.push_back("Hello");
            ? vect.push_back(", ");
            ? vect.push_back("world!");
            ?
            ? std::copy( vect.begin(), vect.end(),
            ??? std::ostream_iterator<std::string>(std::cout) );
            }

            基本上,這算是一個“過得去”的方案,但是有點問題:
            1. 對于不熟悉這個固定用法的人,cout 所有元素所首要考慮算法是 for_each,而不是 copy ,事實上,for_each 也是最符合我們慣常邏輯的算法,因為在不使用 STL 算法的時候,我們使用 for 循環來干這件事。
            2. 可讀性不太良好,ostream_iterator 的使用有點 tricky ,而且也不能用于做其他的事情。

            我想熟悉 boost? 的人已經知道我下面要說什么了,因為用 boost.lambda 做這件事情的確非常漂亮:

            #include <iostream>
            #include <algorithm>
            #include <vector>
            #include <string>

            #include <boost/lambda/lambda.hpp>
            #include <boost/lambda/bind.hpp>

            using namespace boost::lambda;

            int main()
            {
            ? std::vector<std::string> vect;
            ? vect.push_back("Hello");
            ? vect.push_back(", ");
            ? vect.push_back("world!");
            ?
            ? std::for_each( vect.begin(), vect.end(), std::cout << _1 );
            }

            這和前面的程序一樣,輸出我們熟悉的 Hello, world! 。直觀、優雅而且容易修改,例如,如果你不是想要輸出它們的值,而是想要輸出它們的長度,只需要做很少的修改:

            std::for_each( vect.begin(), vect.end(), std::cout << bind(&std::string::length, _1) << "\n" );

            輸出
            5
            2
            6

            bind 的作用是把 lambda 表達式綁定到一個函數或者一個數據成員,在這里的意思,就是對于每一個 string ,都調用其 length() 方法。_1 同樣也可以成為賦值的對象,例如,先執行

            std::for_each( vect[0].begin(), vect[0].end(), _1 = bind(&toupper, _1) );

            然后再把這些 string 輸出,你會得到

            HELLO, world!

            因為那一句對 "Hello" 中的每一個字母調用 toupper ,并把結果寫回。

            =================================================================================

            第一個問題:如何對一個 map 中所有的 key 或者 value 做某件事情?

            當然,這還是取決于你要做的是什么。手寫 for 循環當然是萬能的,但是現在有了那么多的泛型算法,我們可以考慮其他的方案了(這也是眾多 C++ Gurus 推薦的思維方式)如果是把所有的 value 全部 cout 出來,用 boost.lambda 配合 for_each 還是比較優雅的(雖然沒有像 vector 和 list 那樣的優雅):

            #include <iostream>
            #include <algorithm>
            #include <map>
            #include <string>

            #include <boost/lambda/lambda.hpp>
            #include <boost/lambda/bind.hpp>

            using namespace boost::lambda;

            int main()
            {
            ? std::map<int, std::string> strs;
            ? strs[0] = "Hello";
            ? strs[1] = ", ";
            ? strs[2] = "world";
            ? strs[3] = "!";
            ?
            ? std::for_each( strs.begin(), strs.end(),
            ??? std::cout << bind(&std::map<int, std::string>::value_type::second, _1) );
            }

            這樣的輸出如我們所料,就是 Hello, world! 。

            如果想要把 key 也輸出,道理是一樣的,只需要這樣:

            ? std::for_each( strs.begin(), strs.end(),
            ??? std::cout << bind(&std::map<int, std::string>::value_type::second, _1) << '\t'
            ??????????????????? << bind(&std::map<int, std::string>::value_type::first, _1) << '\n'
            ? );

            其結果是:

            Hello?? 0
            ,??????????? 1
            world?? 2
            !??????????? 3

            因此,對于一個 map 中的 value 的操作往往可以依法炮制,如果我們想要在其中尋找 value 為 “world" 的那一個元素,并且輸出它的 key ,只需要一句話:

            ? std::cout <<
            ??? std::find_if( strs.begin(), strs.end(),
            ????? bind(&std::map<int, std::string>::value_type::second, _1) == "world" )->first;

            STL 算法 find_if 接受的第三個參數是一個 prediate ,而生成這種臨時的 functor 正是 lambda 的拿手好戲。上面的這句話也可以用 boost::bind 來做,只需要更改 include 和 using namespace ,代碼本身無需更改。而如果你不借助于它們,你只有手寫循環或者自己寫一個 predicate 。

            當情況變得復雜一些的時候,lambda 的用法也變得更加有趣了:

            #include <iostream>
            #include <algorithm>
            #include <map>
            #include <string>

            #include <boost/lambda/lambda.hpp>
            #include <boost/lambda/bind.hpp>

            using namespace boost::lambda;

            class Person
            {
            public:
            ? Person(){}
            ? Person(const std::string& name) : name_(name){}
            ?
            ? std::string Name()
            ? { return name_; }
            ?
            private:
            ? std::string name_;
            };

            int main()
            {
            ? std::map<int, Person> persons;
            ? persons[123] = Person("Amy");
            ? persons[234] = Person("Ralph");
            ? persons[345] = Person("Simon");
            ? persons[456] = Person("Maggie");

            ? std::for_each( persons.begin(), persons.end(),
            ??? std::cout << bind(&std::map<int, Person>::value_type::first, _1) << '\t'
            ??????????????????? << bind(&Person::Name,
            ??????????????????????????? bind(&std::map<int, Person>::value_type::second, _1)) << '\n'
            ? );

            ? std::cout << "Ralph's Id is: " <<
            ??? std::find_if( persons.begin(), persons.end(),
            ????? bind(&Person::Name,
            ??????? bind(&std::map<int, Person>::value_type::second, _1)) == "Ralph" )->first;
            }

            這里 map 的 value 元素不再是一個單純的 string,我們要輸出的是這個 value 的 Name() ,幸好 lambda 的綁定可以級聯,所以我們仍然可以用 STL 算法在一個表達式之內搞定這些任務:for_each 輸出 key 和 value 的 Name(),而 find_if 找到 value 的 Name() 為 "Ralph" 的那一個元素,輸出是這樣的:

            123???? Amy
            234???? Ralph
            345???? Simon
            456???? Maggie
            Ralph's Id is: 234

            posted on 2006-06-28 13:40 笑笑生 閱讀(131) 評論(0)  編輯 收藏 引用
             
            Copyright © 笑笑生 Powered by: 博客園 模板提供:滬江博客
            国产aⅴ激情无码久久| 亚洲精品无码久久一线| 99久久精品国产综合一区| 99久久无码一区人妻| 久久久久亚洲AV成人网人人网站| 亚洲欧洲精品成人久久曰影片| 亚洲va国产va天堂va久久| 亚洲午夜久久久精品影院| 亚洲乱码日产精品a级毛片久久| 久久婷婷五月综合97色| 色偷偷88欧美精品久久久| 久久香蕉国产线看观看精品yw| 狠狠久久综合伊人不卡| 国产精品禁18久久久夂久| 亚洲v国产v天堂a无码久久| 国产亚洲美女精品久久久久狼| 青青青青久久精品国产h久久精品五福影院1421 | 国产视频久久| 人妻精品久久无码专区精东影业| 国产福利电影一区二区三区久久久久成人精品综合 | 青青草原综合久久| 少妇熟女久久综合网色欲| 国产精品成人久久久久久久| 亚洲AV日韩AV天堂久久| 狠狠色丁香久久婷婷综合_中 | 国产日韩久久免费影院| 国产麻豆精品久久一二三| 一本色综合网久久| 波多野结衣久久精品| 久久亚洲AV无码西西人体| 久久丝袜精品中文字幕| 999久久久免费国产精品播放| 97久久国产亚洲精品超碰热 | 国产精品美女久久福利网站| 久久午夜福利电影| 久久综合伊人77777| 热久久视久久精品18| 久久久久久伊人高潮影院| 国产成人久久精品一区二区三区| 久久受www免费人成_看片中文| 精品国产乱码久久久久软件|