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

隨筆 - 8  文章 - 26  trackbacks - 0
<2025年9月>
31123456
78910111213
14151617181920
21222324252627
2829301234
567891011

常用鏈接

留言簿(5)

隨筆檔案

文章分類

文章檔案

相冊

C++語言

搜索

  •  

最新評論

閱讀排行榜

評論排行榜

轉載自:

http://www.stlchina.org/documents/EffectiveSTL/files/item_41.html

相關參考:http://www.cnblogs.com/oomusou/archive/2007/05/12/744000.html

ptr_fun/mem_fun/mem_fun_ref系列是什么意思的?有時候你必須使用這些函數,有時候不用,總之,它們是做什么的?它們似乎只是坐在那里,沒用地掛在函數名周圍就像不合身的外衣。它們不好輸入,影響閱讀,而且難以理解。這些東西是STL古董的附加例子(正如在條款1018中描述的那樣),或者只是一些標準委員會的成員因為太閑和扭曲的幽默感而強加給我們的語法玩笑?

冷靜一下。雖然ptr_fun、mem_fun和mem_fun_ref的名字不太好聽,但它們做了很重要的工作,而不是語法玩笑,這些函數的主要任務之一是覆蓋C++固有的語法矛盾之一。

如果我有一個函數f和一個對象x,我希望在x上調用f,而且我在x的成員函數之外。C++給我三種不同的語法來實現這個調用:

f(x);                  // 語法#1:當f是一個非成員函數
x.f();                  // 語法#2:當f是一個成員函數
// 而且x是一個對象或一個對象的引用
p->f();                  // 語法#3:當f是一個成員函數
// 而且p是一個對象的指針

現在,假設我有一個可以測試Widget的函數,

void test(Widget& w);            // 測試w,如果沒通過
// 就標記為“failed”

而且我有一個Widget的容器:

vector<Widget> vw;                  // vw容納Widget

要測試vw中的每個Widget,我很顯然可以這么使用for_each:

for_each(vw.begin(), vw.end(), test);      // 調用#1(可以編譯)

但想象test是一個Widget的成員函數而不是一個非成員函數,也就是說,Widget支持自我測試:

class Widget {
public:
void test();            // 進行自我測試;如果沒通過
// 就把*this標記為“failed”
};

在一個完美的世界,我也將能使用for_each對vw中的每個對象調用Widget::test:

for_each(vw.begin(), vw.end(),
&Widget::test);            // 調用#2(不能編譯

實際上,如果世界真的完美,我將也可以使用for_each來在Widget*指針的容器上調用Widget::test:

list<Widget*> lpw;                        // lpw容納Widget的指針
for_each(lpw.begin(), lpw.end(),
&Widget::test);            // 調用#3(也不能編譯

但是想想在這個完美的世界里必須發生的。在調用#1的for_each函數內部,我們以一個對象為參數調用一個非成員函數,因此我們必須使用語法#1。在調用#2的for_each函數內部,我們必須使用語法#2,因為我們有一個對象和一個成員函數。而調用#3的for_each函數內部,我們需要使用語法#3,因為我們將面對一個成員函數和一個對象的指針。因此我們需要三個不同版本的for_each,而那個世界將有多完美?

在我們擁有的世界上,我們只有一個版本的for_each。想一種實現不難:

template<typename InputIterator, typename Function>
Function for_each(InputIterator begin, InputIterator end, Function f)
{
while (begin != end) f(*begin++);
}

這里,我強調當調用時for_each是用語法#1這個事實。這是STL里的一個普遍習慣:函數和函數對象總使用用于非成員函數的語法形式調用。這解釋了為什么調用#1可以編譯而調用#2和#3不。這是因為STL算法(包括for_each)牢牢地綁定在句法#1上,而且只有調用#1與那語法兼容。

也許現在清楚為什么mem_fun和mem_fun_ref存在了。它們讓成員函數(通常必須使用句法#2或者#3來調用的)使用句法1調用。

mem_fun和mem_fun_ref完成這個的方式很簡單,雖然如果你看一下這些函數之一的聲明會稍微清楚些。它們是真的函數模板,而且存在mem_fun和mem_fun_ref模板的幾個變體,對應于它們適配的不同的參數個數和常量性(或缺乏)的成員函數。看一個聲明就足以理解事情怎樣形成整體的:

template<typename R, typename C>            // 用于不帶參數的non-const成員函數
mem_fun_t<R,C>                        // 的mem_fun聲明。
mem_fun(R(C::*pmf)());                  // C是類,R是被指向
// 的成員函數的返回類型

mem_fun帶有一個到成員函數的指針,pmf,并返回一個mem_fun_t類型的對象。這是一個仿函數類,容納成員函數指針并提供一個operator(),它調用指向在傳給operator()的對象上的成員函數。例如,在這段代碼中,

list<Widget*> lpw;                        // 同上
...
for_each(lpw.begin(), lpw.end(),
mem_fun(&Widget::test));      // 這個現在可以編譯了

for_each接受一個mem_fun_t類型的對象,持有一個Widget::test的指針。對于在lpw里的每個Widget*指針,for_each使用語法#1“調用”mem_func_t,而那個對象立刻在Widget*指針上使用句法#3調用Widget::test。

總的來說,mem_fun適配語法#3——也就是當和Widget*指針配合時Widget::test要求的——到語法1,也就是for_each用的。因此也不奇怪像mem_fun_t這樣的類被稱為函數對象適配器。知道這個不應該使你驚訝,完全類似上述的,mem_fun_ref函數適配語法#2到語法#1,并產生mem_fun_ref_t類型的適配器對象。

mem_fun和mem_fun_ref產生的對象不僅允許STL組件假設所有函數都使用單一的語法調用。它們也提供重要的typedef,正如ptr_fun產生的對象一樣。條款40告訴了你這些typedef后面的故事,所以我將不在這里重復它。但是,這使我們能夠理解為什么這個調用可以編譯。

for_each(vw.begin(), vw.end(), test);            // 同上,調用#1;
// 這個可以編譯

而這些不能:

for_each(vw.begin(), vw.end(), &Widget::test);      // 同上,調用#2;
// 不能編譯
for_each(lpw.begin(), lpw.end(), &Widget::test);      // 同上,調用#3;
// 不能編譯

第一個調用(調用#1)傳遞一個真的函數,因此用于for_each時不需要適配它的調用語法;這個算法將固有地使用適當的語法調用它。而且,for_each沒有使用ptr_fun增加的typedef,所以當把test傳給for_each時不必使用ptr_fun。另一方面,增加的typedef不會造成任何損傷,所以這和上面的調用做相同的事情:

for_each(vw.begin(), vw.end(), ptr_fun(test));      // 可以編譯,行為
// 就像上面的調用#1

如果你關于什么時候使用ptr_fun什么時候不使用而感到困惑,那就考慮每當你傳遞一個函數給STL組件時都使用它。STL將不在乎, 并且沒有運行期的懲罰。可能出現的最壞的情況就是一些讀你代碼的人當看見不必要的ptr_fun使用時,可能會揚起眉毛。我認為,那有多讓你操心依賴于你對揚起眉毛的敏感性。

一個與ptr_fun有關的可選策略是只有當你被迫時才使用它。如果當typedef是必要時你忽略了它,你的編譯器將退回你的代碼。然后你得返回去添加它。

mem_fun和mem_fun_ref的情況則完全不同。只要你傳一個成員函數給STL組件,你就必須使用它們,因為,除了增加typedef(可能是或可能不是必須的)之外,它們把調用語法從一個通常用于成員函數的適配到在STL中到處使用的。當傳遞成員函數指針時如果你不使用它們,你的代碼將永遠不能編譯。

現在只留下成員函數適配器的名字,而在這里,最后,我們有一個真實的STL歷史產物。當對這些種適配器的需求開始變得明顯時,建立STL的人們正專注于指針的容器。(這種容器的缺點在條款72033描述,這看起來可能很驚人,但是記住指針的容器支持多態,而對象的容器不支持。)他們需要用于成員函數的適配器,所以他們選擇了mem_fun。但很快他們意識到需要一個用于對象的容器的另一個適配器,所以他們使用了mem_fun_ref。是的,它非常不優雅,但是這些事情發生了。告訴我你從未給你的任何組件一個你過后意識到,呃,很難概括的名字……

posted on 2008-06-26 20:11 楊彬彬 閱讀(1124) 評論(0)  編輯 收藏 引用 所屬分類: STL
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            美女图片一区二区| 亚洲青色在线| 欧美精品v日韩精品v韩国精品v| 夜夜嗨av一区二区三区四季av| 久热精品在线视频| 欧美中文字幕视频| 欧美一区午夜视频在线观看| 欧美一区不卡| 免费日本视频一区| 最近看过的日韩成人| 亚洲人成亚洲人成在线观看| 亚洲国产日韩综合一区| 亚洲人体一区| 亚洲一区日韩| 久久久久国产一区二区| 六月丁香综合| 国产精品亚洲一区| 一区二区自拍| 亚洲欧美一区二区精品久久久| 久久精品欧美日韩| 亚洲欧洲在线播放| 欧美在线观看一二区| 欧美精品久久一区| 国产一区视频在线观看免费| 日韩视频一区二区在线观看| 午夜天堂精品久久久久| 激情校园亚洲| 亚洲国产毛片完整版 | 久久精品国产91精品亚洲| 午夜精品久久| 中文精品视频| 欧美日本亚洲视频| 99精品国产一区二区青青牛奶| 久久精品99国产精品| 亚洲在线1234| 国产日韩欧美在线播放| 欧美一区视频在线| 欧美一级免费视频| 国产精品亚洲激情| 久久久久久午夜| 欧美99久久| 免费的成人av| 国产一区在线观看视频| 亚洲男女自偷自拍图片另类| 亚洲精品乱码久久久久久蜜桃91| 久久爱www久久做| 影音欧美亚洲| 亚洲人成欧美中文字幕| 国产精品99免费看 | 篠田优中文在线播放第一区| 午夜精品一区二区三区在线| 亚洲欧美日韩国产一区二区| 亚洲婷婷在线| 国产一本一道久久香蕉| 久久在线视频| 欧美日韩一区三区| 久久午夜av| 国产精品久久久久免费a∨| 久久人人爽爽爽人久久久| 欧美成人免费全部观看天天性色| 亚洲免费福利视频| 欧美一区国产一区| 亚洲一区成人| 欧美精品福利在线| 欧美激情一二区| 国产一区二区三区精品久久久| 亚洲欧洲一区二区在线观看| 国产综合视频在线观看| 亚洲永久视频| 性视频1819p久久| 国产精品vvv| 亚洲视频精选在线| 亚洲永久免费av| 欧美日韩第一区| 亚洲精品永久免费精品| 亚洲精品色婷婷福利天堂| 美女诱惑一区| 亚洲第一页自拍| 亚洲日韩欧美视频一区| 欧美国产亚洲视频| 正在播放欧美一区| 久久九九有精品国产23| 狠狠综合久久av一区二区小说| 99成人在线| 欧美日韩在线电影| 99视频国产精品免费观看| 亚洲午夜精品福利| 亚洲电影第1页| 亚洲线精品一区二区三区八戒| 欧美日韩欧美一区二区| 亚洲一区二区三区中文字幕| 久久久天天操| 夜夜嗨一区二区| 国产女人精品视频| 老鸭窝91久久精品色噜噜导演| 亚洲电影免费观看高清完整版在线| 亚洲另类视频| 国产视频久久| 国产精品成人播放| 蜜桃av一区| 欧美在线视频导航| 亚洲视频香蕉人妖| 亚洲黄色av| 久久视频在线看| 亚洲欧美日韩国产中文| 日韩一区二区精品葵司在线| 国内成人精品一区| 国产精品自在线| 国产精品日韩一区二区| 欧美日韩小视频| 国产精品videosex极品| 欧美黄色影院| 欧美理论片在线观看| 欧美极品欧美精品欧美视频| 麻豆精品传媒视频| 欧美国产高清| 欧美日韩免费在线| 国产精品免费视频观看| 国产精品乱码| 黄色精品一区| 亚洲美女性视频| 亚洲欧美日韩中文播放| 午夜精品视频一区| 久久久精品国产免大香伊 | 久久视频一区| 欧美成人福利视频| 亚洲国产精品久久久久秋霞蜜臀| 欧美成人日本| 日韩视频免费观看高清在线视频| 日韩一级大片| 久久激情视频| 欧美日韩国产综合网 | 亚洲免费在线电影| 99在线热播精品免费| 久久亚洲精品伦理| 欧美一区二视频在线免费观看| 久久先锋资源| 欧美日韩一二三区| 亚洲第一页在线| 久久不射网站| 99在线热播精品免费99热| 欧美一区二区免费观在线| 久久久久久久91| 国产精品夜夜夜一区二区三区尤| 一区二区三区中文在线观看 | 亚洲欧美经典视频| 久久青草久久| 国产一区二区精品丝袜| 中国成人亚色综合网站| 免费影视亚洲| 久久久国产精品一区二区三区| 欧美体内she精视频在线观看| 禁久久精品乱码| 久久青青草综合| 欧美一区二区三区免费观看| 国产精品视频yy9299一区| 亚洲视频中文字幕| 日韩视频免费观看| 国产老肥熟一区二区三区| 午夜日韩电影| 久久久噜噜噜| 亚洲精品无人区| 日韩视频免费观看高清完整版| 欧美高清视频在线观看| 欧美一区二区在线| 在线视频国产日韩| 亚洲国产日韩一区二区| 欧美日韩八区| 久久先锋影音av| 欧美日韩一区二区三区四区五区| 亚洲午夜激情免费视频| 亚洲欧美日韩综合| 亚洲欧洲一区二区天堂久久| 亚洲精选一区| 在线成人激情视频| 亚洲一区免费| 99国产精品久久久久久久| 香蕉久久夜色精品| 国产精品99久久久久久久vr| 欧美在线一区二区| 亚洲综合色激情五月| 久久综合九色| 久久综合给合| 国产亚洲精品v| 亚洲色无码播放| 亚洲视频1区| 欧美精品色一区二区三区| 麻豆精品传媒视频| 国产一区av在线| 欧美在线免费视频| 久久久久久穴| 欧美精品麻豆| 欧美激情一区二区三区在线| 亚洲欧洲久久| 男人的天堂亚洲| 欧美国产亚洲另类动漫| 精品电影在线观看| 麻豆九一精品爱看视频在线观看免费 | 久久久夜色精品亚洲| 国产亚洲一区在线|