青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

Impossible is nothing  
  愛過知情重醉過知酒濃   花開花謝終是空   緣份不停留像春風來又走   女人如花花似夢
公告
日歷
<2025年11月>
2627282930311
2345678
9101112131415
16171819202122
23242526272829
30123456
統(tǒng)計
  • 隨筆 - 8
  • 文章 - 91
  • 評論 - 16
  • 引用 - 0

導航

常用鏈接

留言簿(4)

隨筆分類(4)

隨筆檔案(8)

文章分類(77)

文章檔案(91)

相冊

搜索

  •  

最新評論

閱讀排行榜

評論排行榜

 

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

從 STL 出現(xiàn)到現(xiàn)在已經這么多年了,泛型算法是它的重要組成,也是其中最“看起來很美”的東西之一。然而在真實的程序設計中,它往往成為程序員的心頭一痛,因為一旦要用 for_each ,accumulate 之類的算法做一些稍微復雜一點的事情,你就會發(fā)現(xiàn)自己一個頭變成兩個大。即便是有了 boost::bind 和 boost.lambda 的幫助,事情也仍然是撲朔迷離,求助于 comp.lang.c++ 雖然有用,但是又何嘗不是一種無奈。好了,現(xiàn)在我開始收集一些來自 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 循環(huán)來干這件事。
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! 。直觀、優(yōu)雅而且容易修改,例如,如果你不是想要輸出它們的值,而是想要輸出它們的長度,只需要做很少的修改:

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

輸出
5
2
6

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

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

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

HELLO, world!

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

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

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

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

#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 接受的第三個參數(shù)是一個 prediate ,而生成這種臨時的 functor 正是 lambda 的拿手好戲。上面的這句話也可以用 boost::bind 來做,只需要更改 include 和 using namespace ,代碼本身無需更改。而如果你不借助于它們,你只有手寫循環(huán)或者自己寫一個 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 的綁定可以級聯(lián),所以我們仍然可以用 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 笑笑生 閱讀(147) 評論(0)  編輯 收藏 引用

只有注冊用戶登錄后才能發(fā)表評論。
網站導航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


 
Copyright © 笑笑生 Powered by: 博客園 模板提供:滬江博客
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            欧美午夜精品久久久久久人妖| 欧美国产日韩a欧美在线观看| 国产亚洲午夜| 欧美日韩在线播放一区| 欧美日韩和欧美的一区二区| 欧美日韩成人在线播放| 欧美性大战久久久久久久| 国产精品嫩草影院av蜜臀| 国产精品国码视频| 国产精品免费视频xxxx| 国产亚洲欧美在线| 亚洲欧洲精品一区二区三区波多野1战4| 亚洲高清久久久| 亚洲一区二区三区免费观看| 久久久久久伊人| 亚洲黄一区二区三区| 亚洲国产精品久久91精品| av不卡在线观看| 性色av一区二区三区红粉影视| 久久婷婷综合激情| 欧美视频三区在线播放| 国产一区美女| 99re在线精品| 久久午夜羞羞影院免费观看| 亚洲三级影院| 久久精品国产99国产精品| 欧美精品粉嫩高潮一区二区| 国产私拍一区| 这里只有精品在线播放| 浪潮色综合久久天堂| 99国产一区| 美女精品网站| 国产欧美日韩一区二区三区在线 | 久久精品欧美| 欧美午夜精品久久久| 在线播放视频一区| 亚洲欧美激情四射在线日 | 亚洲女女做受ⅹxx高潮| 久久综合激情| 国产日韩欧美高清免费| 亚洲特级毛片| 亚洲电影免费观看高清完整版在线 | 亚洲欧美激情诱惑| 欧美成人一区二区| 亚洲欧美欧美一区二区三区| 欧美肥婆在线| 在线观看国产精品网站| 久久国产视频网站| 午夜精品婷婷| 国产精品日韩欧美一区| 亚洲在线成人| 一区二区三区国产| 欧美三级在线播放| 一区二区三区欧美在线| 亚洲片区在线| 欧美精品一区二区三区一线天视频 | 亚洲免费在线播放| 一区二区欧美视频| 欧美日韩一区二区免费在线观看 | 久久久久久久尹人综合网亚洲| 一区二区三区日韩精品| 欧美三级视频在线播放| 一区二区三区视频在线播放| 91久久久亚洲精品| 欧美黄色免费| 一本不卡影院| 夜夜爽99久久国产综合精品女不卡| 欧美福利在线观看| 一区在线免费| 欧美激情精品久久久久久蜜臀 | 国产手机视频精品| 久久蜜臀精品av| 麻豆精品传媒视频| 亚洲激情av| 99国产精品国产精品久久| 欧美喷水视频| 香蕉免费一区二区三区在线观看 | 91久久黄色| 欧美亚洲第一区| 欧美在线网站| 美国十次成人| 在线视频你懂得一区| 亚洲在线中文字幕| 在线播放豆国产99亚洲| 亚洲欧洲美洲综合色网| 国产精品福利网| 久久精品一区二区三区四区 | 久久精品视频va| 亚洲在线视频免费观看| 久久全球大尺度高清视频| 亚洲免费综合| 亚洲成在人线av| 99精品国产在热久久婷婷| 国产美女诱惑一区二区| 欧美a级片网| 欧美日韩一区综合| 久久人人爽人人| 欧美视频二区36p| 久久五月天婷婷| 国产精品国产a| 欧美成人精品影院| 国产精品久久久久毛片大屁完整版 | 国产精品高潮粉嫩av| 久久综合久久综合久久| 欧美日韩情趣电影| 美日韩精品视频免费看| 国产精品欧美日韩一区| 亚洲人成亚洲人成在线观看图片| 国产视频在线观看一区二区三区| 亚洲精品视频一区二区三区| 国产午夜精品美女视频明星a级| 亚洲国产成人久久综合| 国产麻豆视频精品| 亚洲乱码国产乱码精品精天堂| 韩国成人理伦片免费播放| 亚洲视频精选| 一区二区三区国产在线| 蜜臀av在线播放一区二区三区| 欧美一级播放| 欧美体内she精视频| 亚洲国产第一页| 亚洲福利视频免费观看| 欧美在线|欧美| 亚洲专区在线| 欧美另类高清视频在线| 欧美成人a∨高清免费观看| 国产亚洲成av人在线观看导航| 一区二区免费看| 一区二区三区精品国产| 欧美日韩国产在线一区| 91久久精品国产91久久性色tv| 樱桃国产成人精品视频| 欧美综合第一页| 久久九九热免费视频| 国产精品视频网| 一个色综合导航| 亚洲免费人成在线视频观看| 欧美日韩亚洲免费| 日韩亚洲精品在线| 亚洲校园激情| 国产精品高清在线| 午夜激情一区| 久久免费精品日本久久中文字幕| 国产一区二区三区日韩| 久久精品国产一区二区电影| 久久午夜色播影院免费高清| 精品不卡一区| 男人的天堂亚洲| 一本久久精品一区二区| 性久久久久久久久久久久| 亚洲精品综合精品自拍| 亚洲天堂黄色| 久久综合中文| 亚洲国产黄色| 一本久久青青| 国产精品手机在线| 久久国产精品久久久久久久久久 | 久久福利影视| 伊人成人在线视频| 美日韩丰满少妇在线观看| 亚洲精品一线二线三线无人区| 亚洲一区二区三区涩| 国产欧美日韩另类一区| 久久夜色精品国产噜噜av| 91久久久久久| 欧美亚洲免费在线| 在线精品观看| 欧美体内she精视频| 久久国产一区| 亚洲精选国产| 久久久久一区二区三区四区| 日韩一区二区久久| 国产日韩精品一区| 欧美粗暴jizz性欧美20| 亚洲一区欧美| 亚洲激情成人在线| 久久精品国产亚洲a| 亚洲精品视频在线观看免费| 国产精品一区三区| 欧美激情网站在线观看| 午夜久久久久| 一区二区不卡在线视频 午夜欧美不卡在 | 亚洲欧洲另类| 国产日本亚洲高清| 欧美激情区在线播放| 亚洲欧美经典视频| 亚洲欧洲精品一区| 久久婷婷激情| 亚洲欧美一区二区三区极速播放| 亚洲国产精品一区制服丝袜| 国产精品视频一| 欧美精品在线一区| 久久久久久久久蜜桃| 亚洲欧美在线一区二区| 日韩天堂av| 亚洲欧洲日产国产综合网| 玖玖国产精品视频| 久久av红桃一区二区小说| 中文欧美日韩| 99日韩精品|