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

隨筆 - 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>
            欧美暴力喷水在线| 亚洲毛片一区二区| 亚洲美女尤物影院| 亚洲精品韩国| 亚洲每日更新| 亚洲性图久久| 欧美一级一区| 欧美99在线视频观看| 亚洲欧洲三级电影| 亚洲美女视频在线免费观看| 一本一本久久a久久精品牛牛影视| 欧美高清在线播放| 亚洲美女视频在线观看| 亚洲图片在线| 久久久久久精| 欧美日韩情趣电影| 国产午夜精品久久久| 极品少妇一区二区| 99精品福利视频| 久久精彩视频| 亚洲精品欧美激情| 欧美一区二区三区久久精品| 蜜臀va亚洲va欧美va天堂| 欧美视频日韩视频| 国产一区二区三区四区| 一区二区日韩| 欧美肥婆bbw| 羞羞视频在线观看欧美| 欧美国产极速在线| 韩国一区二区在线观看| 亚洲一区成人| 亚洲国产精品va在看黑人| 一区二区高清在线| 牛牛影视久久网| 国产一级一区二区| 亚洲欧美一区二区三区在线| 欧美成年人视频| 欧美一区二区视频在线观看2020| 欧美人与性动交a欧美精品| 国产在线精品二区| 校园激情久久| 中国av一区| 欧美精品麻豆| 亚洲精品国产精品国自产在线 | 久久在线91| 国产精品亚洲视频| 一本色道久久精品| 亚洲国产精品毛片| 久久久久久噜噜噜久久久精品| 国产精品亚洲综合久久| 亚洲一区在线播放| 亚洲美女区一区| 欧美日韩伊人| 亚洲性线免费观看视频成熟| 欧美激情欧美狂野欧美精品 | 久久精品视频免费| 国产亚洲成av人片在线观看桃| 亚洲永久在线| 亚洲一区二区在| 国产美女在线精品免费观看| 午夜一区二区三区在线观看| 一区二区精品在线观看| 欧美日韩一区不卡| 亚洲欧美综合精品久久成人| 日韩一区二区福利| 国产精品激情电影| 国产精品久久久久久久久| 欧美高清在线播放| 99日韩精品| 99热在这里有精品免费| 欧美日韩激情小视频| 一区二区三区日韩| 一区二区三区四区五区在线| 欧美日韩一区二区三区| 亚洲欧美视频一区| 欧美一级在线视频| 亚洲高清av| 亚洲精品一区二区三区婷婷月| 欧美日韩精品欧美日韩精品| 亚洲图片你懂的| 先锋影院在线亚洲| 亚洲国产精品久久久久秋霞影院| 亚洲国产第一页| 欧美视频网站| 久久综合狠狠| 欧美日韩在线不卡一区| 久久精品人人做人人爽| 欧美成人精品激情在线观看| 亚洲午夜精品久久久久久浪潮| 亚洲欧美综合网| 亚洲精品永久免费| 篠田优中文在线播放第一区| 在线欧美日韩国产| 一本色道久久综合一区| 国产日韩一区二区三区在线| 美女在线一区二区| 国产精品久久久久久久久婷婷| 久久久精品一区| 欧美久久视频| 久久婷婷影院| 国产精品国产三级国产普通话99| 久久久女女女女999久久| 欧美理论视频| 蜜桃精品一区二区三区| 国产精品美女久久久浪潮软件| 免费日韩av电影| 国产精品免费观看视频| 欧美韩国日本综合| 国产午夜精品在线观看| 日韩网站在线| 亚洲精品在线免费| 久久亚洲综合色| 欧美综合国产精品久久丁香| 欧美女同视频| 亚洲二区在线| 韩国av一区二区三区在线观看 | 亚洲国产一区二区三区青草影视 | 亚洲无限乱码一二三四麻| 亚洲精品日韩在线观看| 久久久免费精品| 久久精品国产欧美激情| 欧美日韩一本到| 亚洲人成绝费网站色www| 在线观看亚洲一区| 久久精品一区二区国产| 久久精品国产亚洲一区二区三区| 欧美日韩亚洲成人| 欧美大片在线影院| 亚洲天堂免费观看| 欧美成人中文字幕在线| 欧美电影免费观看高清| 伊伊综合在线| 久久久成人网| 六月婷婷久久| 在线欧美视频| 欧美电影免费网站| 亚洲三级观看| 在线视频日韩| 国产精品久久久久久五月尺| 亚洲理论在线观看| 亚洲在线视频网站| 国产欧美短视频| 久久久999精品| 亚洲国产欧美一区二区三区久久| 亚洲国产高清在线| 欧美高清在线| 在线亚洲免费| 久久久久久久久综合| 亚洲国产精品999| 欧美精品亚洲二区| 日韩一级大片在线| 欧美资源在线观看| 在线观看亚洲视频| 欧美精品在线视频观看| 亚洲视频成人| 久久综合伊人| 一区二区三区精品久久久| 国产精品久久网| 久久综合色天天久久综合图片| 欧美激情精品久久久久| 亚洲午夜精品久久久久久浪潮| 国产精品尤物| 蜜臀久久99精品久久久久久9| 亚洲精品乱码| 久久精品一级爱片| 99国产精品一区| 国产一区二区精品久久99| 欧美成人网在线| 亚洲综合三区| 亚洲国产婷婷香蕉久久久久久| 亚洲综合视频在线| 亚洲第一网站| 国产伦一区二区三区色一情| 麻豆精品在线观看| 亚洲无人区一区| 亚洲黄色尤物视频| 久久久亚洲欧洲日产国码αv| 一本久道久久综合婷婷鲸鱼| 国产亚洲精品v| 国产精品国产a| 欧美电影资源| 久久se精品一区精品二区| 亚洲伦理在线| 欧美大片免费观看| 久久精品论坛| 亚洲综合大片69999| 亚洲高清在线观看| 国产色产综合色产在线视频| 欧美日韩岛国| 欧美+日本+国产+在线a∨观看| 午夜久久久久| 亚洲影院免费观看| 一区二区三区国产在线观看| 欧美黄色一区二区| 久热精品视频| 久久一区欧美| 久久三级视频| 久久婷婷综合激情| 久久青草欧美一区二区三区| 欧美一区二区三区四区在线观看地址|