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

huaxiazhihuo

 

stl的抽象缺陷終結

古龍說過,一個人的最大優(yōu)點往往將是其致命的弱點。這句話用在stl的迭代器上,最是合適不過。stl通過迭代器來解耦容器與算法,可謂擊節(jié)贊嘆;但是,讓迭代器滿世界的到處亂跑,未免就大煞風景。此話怎講?

其實,有些語言就沒有迭代器的概念,并且還活得很優(yōu)雅,好比haskelllist啊、tree啊,壓根就不需要什么迭代器,只需要模式匹配,體現其數據結構的遞歸特點,就可以很優(yōu)雅地表達算法。就是javac#C++這幾個破面向對象語言,才需要大用特用迭代器,沒有迭代器就活不下去了。迭代器的出現就是為了彌補其語言喪失清晰表達遞歸數據結構的能力。看到haskelllistc++stl下的對應樣子,很多人都表示很難過,因為stl里面,list根本就沒有tail函數,更逞論支持listtail還是一個list這樣絕妙的idea。一切必須通過迭代器這個萬金油來糊弄其尷尬的困境。

隨便來看看幾行stl算法函數的代碼

Vector<int> nums = {..};
find(nums.begin(), nums.end(), 
2);
remove_if(nums.begin(), nums.end(), _1 
>= 0); //為了省事,用了bll的風格,在c++11中,要從零開始造一個bll風格的輪子,不能更方便,大概也就兩三百行的代碼

看到沒有,你信不信,隨便統計一下,一打的algorithm函數,起碼就有12個函數的調用之道,必須傳遞container.begin()container.end()beginend這對兄弟,總是成雙成對的出現,說明了一件事情,就是從一開始,它們必須被打包在一起,而不應該硬生生地將它們拆開。知道這一拆開,帶來多少問題嗎?代碼上的累贅還算是小事,比如,簡潔清晰流暢的find(nums, 2),卻要生硬的寫成find(nums.begin(), nums.end(), 2)。當然,這種api設計,也并非一無是處,起碼,在表達容器里面的部分區(qū)間時,很方便,好比下面的代碼

int nums[10] = {…};

find(nums+1, end(nums)-1, 2);

看起來,好像的確挺方便的,將beginend放在一起,要表達這樣的概念,似乎就有些麻煩,但其實,這是假象,當角度變換時,我們可以會有更方便的方式來表達這樣的需求。最起碼,容器的部分區(qū)間也應該是由容器本身來表達,而不應轉嫁給迭代器來應付,數組的部分也是數組,樹的分支也是樹,這樣的概念,就應該由容器本身來定義。像是哈希表就不支持部分區(qū)間的概念。

為何algorithm的算法,全部(不是基本)都要求一對迭代器。那是因為這些算法的輸入對象,本來就是一個數據集合。而一個迭代器無法完整地表達一個容器,起碼必須一對迭代器才能完整地表達一個數據集。但是,用一對迭代器來作為入參,和用一個區(qū)間作為入參,它所體現抽象的側重點完全不同,而由于此種不同,最后的演變結果,也是天淵之別,即是一對迭代器設計思路是淵,自然,而區(qū)間的設計方案,顯然是天。

再次回顧上文的結尾,findfind_ifremove, remove_copy, remove_copy_if, remove_if,……有沒有感受,一股濃濃的過程式風格,十分的笨重,明顯的非正交,濃烈的c語言風格。對于這樣的api,讓本座對委員會的那幫老不死,徹底的絕望了。他們(它們)的審美觀,停留在很低很低的層次上。

beginend拆分開來的最大問題,其實也就只是,前一個函數的處理結果,不能平滑的傳遞到下一個函數里面去。比如說,現在函數make_nums返回vector<int>,試比較一下,高下立判。

auto nums = make_nums();
find(nums.begin(), nums.end(), 
2); //一對迭代器作為入參
find(make_nums(), 2);//直接數據區(qū)間作為入參

說了這么多,我們強烈要求的僅僅是函數風格的api,正交式的函數設計,前一個函數的處理結果可以平滑地傳遞給下一個函數。總結algorithm的一坨函數,本質上只需filterfoldmapinsert(copy)這屈指可數的幾個函數就可以自由地組合出來,并且還能組合出來algorithm上沒有的效果。首先,這幾個函數的返回結果都是數據區(qū)的數據對象(里面有beginend的成員函數,用以返回迭代器)。其次,就是在迭代器上面做文章,以支持filtermap等操作,也就是在*++!=這幾個運算符上做花樣,要達到filtermap的效果,很容易的。至于像是要求隨機訪問迭代器概念的函數,太常用的就做到array_view里面好了,或者就明確規(guī)定入參就是array_view

然后stl里面還臆造了一種好像叫做insert_iterator迭代器類型的適配器,用以通過迭代器的語法往容器里頭插入數據,好像很玄妙,實則就是強行拔高迭代器的用途,完全就違背了迭代器出現的初衷。這種扭曲的想法,完全就是上面那一坨病態(tài)api的產物。所以,原本的api設計,算法函數必須以容器(數據區(qū)間)為入參,內部調用其beginend成員函數獲得迭代器來遍歷容器的函數,何其清晰的設計思路。但是,stl的設計思路,導致迭代器泛濫,甚至連客戶層面的代碼也大把大把的迭代器,于是迭代器的問題就接二連三的產生,什么失效啊,什么firstlast匹對錯誤。還有,導致容器里面的關于迭代器的成員函數多了一倍,哈希表里面也沒有類似于C#DictionaryKeysValues屬性函數,這些用起來很方便的,不是嗎?

stl的這種api設計思路完全不是以方便使用為主,而是以滿足自己的獨特口味為目的。看看find函數,它返回一個迭代器,所以,我們使用時,必須通過用end來判斷要找的東西是否在區(qū)間里面,

auto found = find(nums.begin(), nums.end(), 2);

if (found != nums.end()){…}

依本座看,直接就返回指針好了,指針為nullptr,就表示元素找不到,代碼變成這樣

if (auto found = find(nums, 2)){…}

代碼合并成一行,不用再和end比較了。更重要的是,返回結果就是指針,類型非常明確,可以平滑的傳遞到別的函數里;而不是迭代器類型,誰知道迭代器類型是什么類型。template這種東西的類型,能明確下來時,就盡快明確下來。至于說,有些區(qū)間的元素不支持返回地址,好比,vector<bool>,很簡單,那就不支持好了。本座編寫c++代碼的原則之一,不求大而全,需求專一,絕不會因為個別同學,就犧牲大多數情況下清晰方便高效的api風格。對于這些異數,必要時,用奇技淫巧解決。你知道,因為多繼承,虛繼承,把成員函數指針這個簡潔的概念搞得非常復雜,不能按正常人方式來使用了,嚴重影響成員函數的用范圍,一直讓本座耿耿于懷。其實,95%以上的情況下,我們就僅僅需要普通成員函數指針而已,另外的5%,也都可以用普通成員函數來封裝。所以,為了彌補這個遺憾,本座做了一個精簡版的delegate,只接受全局函數和普通成員函數,當字段object為空,就表示字段函數指針是全局函數,不為空,就表示函數指針是成員函數。至于其他一切奇奇怪怪的函數,本座的這個delegatesay no,明確拒絕。

stl的這種獨特到處都是,boost更是將其發(fā)揚光大,反正設計出來的api,就是不考慮讓你用的舒爽,二進制的布局,更加一塌糊涂。比如,any的使用,是這樣子用的,cout << any_cast<int>(anyValue),這里還好,假如要分別針對any的實際類型來寫代碼,必須這樣子:
if(anyValue.type() == typeid(int))
    cout 
<< any_cast<int>(anyValue);
else if (anyValue.type() == typeid(double))
    cout 
<< any_cast< double >(anyValue);

這種對類型安全無理取鬧的強調,讓人火冒三丈。要本座說,直接在any里面添加Cast模板成員函數,結果就返回指針好了,指針為空,就表示類型不匹配,代碼就變成這樣

if(auto value = anyValue.Cast<int>())
    cout 
<< *value;
else if(auto value = anyValue.Cast< double >())
    cout 
<< *value;

是否就沒那么心煩呢。另外,鑒于stl對于反射的拒絕,采用virtual+template的類型拭擦大法來彌補,其實并不怎么完美。本座用反射重新實現的any,比stlany好多了,不管是性能、編譯速度、使用方便上,都是要好太多。還有,stlany,要為每個用到的類型都要生成一個實實在在的多態(tài)具體類,每個類都要有一個專門的虛函數表對應,這些可都要寫到二進制文件里面,代碼就是這樣膨脹起來的。總之,stl回避反射后,反射就以另一種形式回歸,好比virtual+template,好比%d%s,好比locale的那些facet實現, 這些動態(tài)機制各自為政,各種混亂。還不如干脆就從源頭上系統化公理化地給予終極解決。

所以,總體上感受stl設計思路上存在的路線,就是太在意于c++語言本身上的特點,受語言自身的缺陷復雜影響太多,忽略了真正的需求,太多的臆造需求,強行讓需求來遷就語言,而不是讓語言來配合基礎庫的實際普遍需求,需求才是根本,為了可以最方便,最清晰,最性能的基礎庫,完全可以大規(guī)模地使用宏、挖掘語言里面最黑暗的邊角料,甚至為了庫的清晰性,可以拒絕那些用了復雜特性的數據結構,比如多繼承,虛繼承等無聊玩意。

概括起來,路線問題導致最終的正果,也即是stl的具體弱雞表現就是,最根本是二進制接口使用上的重重阻礙,誰敢在動態(tài)庫api使用stl的數據類型。其次是以下5小點:

1、內存分配器不應該是容器的模板參數,對allocator的處理太過草率,當初這里必須做深入的挖掘,c++完全可以實現一定程度上的垃圾回收功能,比如arean allocator,不必一一回收在arena allocator上分配的對象,只需一次性釋放arena allocator的內存,達到多次分配,一次釋放的高性能效果,還避免內存泄露,也不用直接面對循環(huán)引用的怪胎設計問題。現有的內存管理策略,把壓力都放在智能指針上;

2、提供的通用容器不夠完備;原本stl的數據結構就大可滿足所有正常和非正常的使用場合,比如滿足侵入式的鏈表需求,比如不管理元素生命周期的容器等;

3、過多的暴露迭代器,迭代器的應用范圍過廣,stl的算法函數用起來很不方便;

4、回避動態(tài)類型反射信息,對數據的輸入輸出支持非常單薄,包括字符串處理、文件讀寫、網絡數據收發(fā)等,標準庫上的現有那點小功能,僅僅是聊勝于無而已,難堪大任;

5、非容器系的實用類太少;

一句話,目前stl的使用,還是遠遠不夠爽。原本用上stl的代碼,應該可以更短、更快、更小。只可惜,stl在通過迭代器實現算法與容器的分離之后,就停步不前,其設計體系在別的地方,鮮有建樹創(chuàng)新。戰(zhàn)略高度過于局促,很多復雜難搞的問題,其實都蘊含著絕大的機遇,而stl都一一回避,真是回避得好!


posted on 2017-07-10 18:30 華夏之火 閱讀(976) 評論(0)  編輯 收藏 引用 所屬分類: c++技術探討

導航

統計

常用鏈接

留言簿(6)

隨筆分類

隨筆檔案

搜索

積分與排名

最新評論

閱讀排行榜

評論排行榜

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            亚洲免费高清| 国产有码一区二区| 亚洲资源在线观看| 欧美多人爱爱视频网站| 国产欧美日韩一级| 久久男人资源视频| 久久久久久一区| 91久久精品一区| 99re国产精品| 国产日韩欧美中文| 亚洲第一主播视频| 欧美精品激情在线观看| 亚洲一区综合| 久久精品综合一区| 一区二区三区欧美成人| 亚洲性图久久| 亚洲二区精品| 一区二区三区高清不卡| 韩国av一区| 亚洲精品久久久久久下一站| 国产精品人人做人人爽| 美女主播精品视频一二三四| 欧美日韩爆操| 久久久亚洲综合| 欧美日本中文| 欧美不卡视频一区| 国产精品成人免费视频| 毛片一区二区三区| 国产精品久久久久久久久久三级 | 鲁鲁狠狠狠7777一区二区| 亚洲精选一区| 欧美一区久久| 亚洲影音先锋| 欧美成人午夜免费视在线看片| 亚洲欧美日韩综合| 欧美成人a视频| 久久久噜噜噜| 国产精品揄拍一区二区| 亚洲国产视频一区二区| 国内精品久久久久影院 日本资源 国内精品久久久久伊人av | 亚洲人精品午夜| 中日韩午夜理伦电影免费| 在线观看亚洲精品| 香蕉久久夜色精品| 亚洲欧美激情一区二区| 欧美日韩1234| 久久天天躁狠狠躁夜夜爽蜜月| 欧美日韩在线观看视频| 亚洲盗摄视频| 亚洲大胆人体在线| 久久精品成人| 久久久夜精品| 国产一区二区三区四区老人| 亚洲一区二区成人在线观看| 一区二区欧美精品| 欧美大胆成人| 亚洲福利在线看| 亚洲激情专区| 免费成人性网站| 亚洲第一区中文99精品| 在线看国产日韩| 久久夜色精品国产| 女人色偷偷aa久久天堂| 亚洲第一黄色| 你懂的国产精品永久在线| 国产美女精品免费电影| 久久激情五月丁香伊人| 国产老女人精品毛片久久| 亚洲午夜一区二区| 欧美一区二区三区在线视频| 国产精品高潮呻吟久久| 亚洲一区二区在线免费观看视频| 亚洲午夜久久久久久久久电影院| 欧美午夜一区| 亚洲欧美中文在线视频| 久久精品视频在线免费观看| 激情亚洲网站| 欧美成人嫩草网站| 日韩一区二区久久| 欧美一区二区三区视频| 国产一区二区三区四区五区美女 | 美国十次成人| 亚洲国产精品一区制服丝袜| 欧美电影免费观看| 一区二区国产精品| 久久精品1区| 亚洲国产视频直播| 欧美视频在线观看| 亚洲欧美日韩一区二区在线| 久热爱精品视频线路一| 亚洲乱码国产乱码精品精可以看| 欧美网站在线观看| 午夜精品理论片| 亚洲国产精品va在线看黑人动漫| 中文无字幕一区二区三区| 国产欧美一区二区精品性色| 蜜桃久久精品乱码一区二区| 99在线精品视频| 老司机午夜精品| 日韩网站在线观看| 国产一区二区av| 欧美日韩蜜桃| 久久精品国产成人| 一本色道久久精品| 老司机免费视频一区二区三区| 亚洲视频一区| 亚洲国产精品精华液2区45| 国产精品草草| 欧美精品电影| 久久精品在这里| 亚洲一区二区免费视频| 欧美国产在线观看| 久久xxxx精品视频| 亚洲无线一线二线三线区别av| 国产一区二区精品久久91| 欧美日韩国产首页| 久久久久久尹人网香蕉| 亚洲一区二区三区乱码aⅴ| 亚洲电影在线观看| 浪潮色综合久久天堂| 亚洲欧美日韩区| 在线性视频日韩欧美| 在线电影院国产精品| 国产日产精品一区二区三区四区的观看方式| 老**午夜毛片一区二区三区| 香蕉久久a毛片| 亚洲一区中文字幕在线观看| 91久久久亚洲精品| 欧美 日韩 国产精品免费观看| 欧美在线亚洲| 欧美在线在线| 欧美一区二区三区日韩| 亚洲永久在线| 亚洲一区二三| 亚洲制服av| 亚洲一区二区三区涩| 亚洲少妇一区| 亚洲一区日本| 欧美日韩在线观看一区二区| 亚洲午夜av在线| 久久久久综合网| 亚洲天堂av在线免费| 久久精品免视看| 午夜精品影院| 亚洲一区二区三区中文字幕在线| 亚洲高清av在线| 国产一区二区成人| 国产精品一区二区你懂的| 欧美婷婷在线| 欧美视频一区在线观看| 欧美日韩日韩| 国产精品免费一区豆花| 欧美三级乱人伦电影| 国产精品二区二区三区| 国产精品成人av性教育| 国产精品v欧美精品∨日韩| 欧美系列精品| 国产农村妇女毛片精品久久莱园子| 国产精品国产三级国产a| 国产精品视频成人| 一区二区三区中文在线观看| 在线观看欧美| 一区二区三区鲁丝不卡| 亚洲欧美日韩视频二区| 久久精品综合| 欧美粗暴jizz性欧美20| 亚洲巨乳在线| 亚洲欧美日韩精品久久奇米色影视| 性久久久久久久| 米奇777在线欧美播放| 欧美片在线观看| 国产精品自在欧美一区| **欧美日韩vr在线| 一区二区三区欧美在线| 欧美一区网站| 亚洲丰满在线| 亚洲精品之草原avav久久| 亚洲一级片在线看| 久久夜色精品亚洲噜噜国产mv| 欧美国产日韩一区| 国产精品一区二区久久久| 最近看过的日韩成人| 亚洲欧美偷拍卡通变态| 另类激情亚洲| 在线亚洲激情| 久久免费视频在线观看| 欧美小视频在线观看| 亚洲大片av| 午夜精品一区二区在线观看 | 国产一区二区三区自拍| 在线看无码的免费网站| 亚洲午夜在线观看| 欧美肥婆bbw| 亚洲女同在线| 欧美日韩和欧美的一区二区| 国产在线日韩| 午夜在线成人av| 亚洲精品免费电影| 免费欧美网站| 精品99一区二区|