• <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>

            S.l.e!ep.¢%

            像打了激速一樣,以四倍的速度運轉,開心的工作
            簡單、開放、平等的公司文化;尊重個性、自由與個人價值;
            posts - 1098, comments - 335, trackbacks - 0, articles - 1
              C++博客 :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理

            排序比較函數:<符號你重載對么了么?

            Posted on 2011-10-15 08:00 S.l.e!ep.¢% 閱讀(801) 評論(0)  編輯 收藏 引用 所屬分類: C++
            前段時間整理臺歷的邏輯數據時考慮到需要去兼容已發布的照片書數據,很多地方做了兼容處理,比如下面這個例子:

            ????? 在很多時候,我們常常會使用map儲存一些需要經常查詢數據結構,而map的key在一開始設計的時候往往不多加思索,很容易就認為它就是個純ID,比如一個數字,或者一個字符串。當隨著產品變得復雜,或者不同數據結構的添加,這個假設往往不堪一擊—-比如在網游中的游戲ID竟然被認為是唯一的Key,而實際上如果涉及到服務器合并,這個ID也就不那么唯一了。很顯然需要解決這個問題就是擴充原來的Key:要么還是將附加信息直接和原先的Key合并,要么將它倆合并到一個數據結構中—-而后者會引來一個小問題:

            ?????? 如果我把這個Key儲存在某個有序容器中,我就需要重新告訴他各個key是按照什么順序排序的。

            ????? 在做照片書的時候,服務器告訴你:哦,我們的模板ID就是唯一標識了,你拿這個ID就可以得到我這邊關于這個作品的所有數據。而到了做臺歷的時候,服務器換了種說法:不好意思,為了充分利用資源,我們很多臺歷用得是同一個模板,你還要告訴我這個臺歷的產品ID。于是shit就這么發生了。

            ?????? 可憐的Key就從string templateID,變成了struct TemplateKey{string m_sTemplateID;string m_sProductID};嗯,這不是什么問題,比較煩的就是如果你用map來儲存,那你就得自己重寫排序比較函數,于是你有了如下的代碼:

            1booloperator<(constTemplateSearchKey &searchKey) const
            2{
            3????????returnm_sProductID < searchKey.m_sProductID &&
            4???????????????m_sTemplateID < searchKey.m_sTemplateID;
            5}

            可惜的是這樣的代碼大錯特錯,試試下面的代碼

            01#include <iostream>
            02#include <map>
            03#include <string>
            04??
            05usingnamespacestd;
            06??
            07structTemplateSearchKey
            08{
            09????string m_sProductID;
            10????string m_sTemplateID;
            11????TemplateSearchKey(conststring& sTemplateID,conststring& sProductID)
            12????{
            13????????m_sTemplateID??? = sTemplateID;
            14????????m_sProductID??? = sProductID;
            15????}
            16??
            17????booloperator<(constTemplateSearchKey &searchKey) const
            18????{
            19????????returnm_sProductID < searchKey.m_sProductID &&
            20???????????????m_sTemplateID < searchKey.m_sTemplateID;
            21????}
            22};
            23??
            24intmain()
            25{
            26????map<TemplateSearchKey,string> testMap;
            27????TemplateSearchKey key("","2");
            28????TemplateSearchKey key1("","1");
            29????TemplateSearchKey key2("","3");
            30????testMap[key] = "a";
            31????testMap[key1] = "b";
            32????testMap[key2] = "c";
            33????cout<<testMap[key]<<endl;
            34????system("pause");
            35????return0;
            36??
            37}

            做調整:

            1booloperator<(constTemplateSearchKey &searchKey) const
            2{
            3??
            4???????returnm_sProductID < searchKey.m_sProductID ||
            5??????????????m_sTemplateID < searchKey.m_sTemplateID;
            6??
            7}

            ?

            而這個連編譯都是不通過的……出一個ASSERT告訴你你的<符號是無效的。

            01template<class_Pr, class_Ty1, class_Ty2> inline
            02bool__CLRCALL_OR_CDECL _Debug_lt_pred(_Pr _Pred, const_Ty1& _Left, const_Ty2& _Right,
            03??
            04????constwchar_t*_Where, unsigned int_Line)
            05??
            06{??? // test if _Pred(_Left, _Right) and _Pred is strict weak ordering
            07??
            08if(!_Pred(_Left, _Right))
            09??
            10????return(false);
            11??
            12elseif(_Pred(_Right, _Left))
            13??
            14????_DEBUG_ERROR2("invalid operator<", _Where, _Line); //ASSERT出來的點
            15??
            16return(true);
            17??
            18}

            于是趕緊琢磨了下,改了:

            01booloperator<(constTemplateSearchKey &searchKey) const
            02{
            03??
            04????if(m_sProductID == searchKey.m_sProductID)
            05????{
            06????????returnm_sTemplateID < searchKey.m_sTemplateID;
            07????}
            08????else
            09????{
            10????????returnm_sProductID < searchKey.m_sProductID;
            11????}
            12};

            OK,編譯通過,運行沒問題。可問題也來了,如果有3個成員呢?4個5個呢?一個比較好的方法就是直接把每個成員hash成一個數值,然后各個數值鏈起來,通過比較最后這個值來確定大小。于是就想了,為啥不學JAVA直接把排序功能切成兩部分—-兩個函數hasCode和equals,一個用來確定東西怎么排序,而另外一個用來確定是不是同一個東西。而STL這種做法雖然簡練卻晦澀,需要用戶自己去考慮我寫完的排序函數是不是符合傳說中的排序三定律(有時候即使符合也不能完全反應用戶原意)。

            亚洲精品97久久中文字幕无码 | 国产精品毛片久久久久久久| 久久久久久亚洲Av无码精品专口 | 精品久久久久久99人妻| 久久99精品国产| 久久久久亚洲AV综合波多野结衣| 久久久老熟女一区二区三区| 久久天天躁狠狠躁夜夜96流白浆 | 亚洲伊人久久大香线蕉综合图片| 亚洲一级Av无码毛片久久精品| 久久人人爽人人爽人人片av麻烦 | 亚洲国产成人精品久久久国产成人一区二区三区综 | 午夜精品久久久久久影视777| 久久AV高潮AV无码AV| 久久精品午夜一区二区福利 | 久久精品国产精品亚洲艾草网美妙| 新狼窝色AV性久久久久久| 国产成人久久精品激情 | 久久亚洲国产精品一区二区| 久久九九久精品国产免费直播| 婷婷伊人久久大香线蕉AV| 久久国产精品一区| 97超级碰碰碰久久久久| 亚洲国产成人久久精品99 | 草草久久久无码国产专区| 99精品国产99久久久久久97| 99精品久久精品一区二区| A级毛片无码久久精品免费| 久久久这里有精品中文字幕| 亚洲嫩草影院久久精品| 久久久久亚洲AV成人网| 久久精品国产99久久久| 欧美伊人久久大香线蕉综合69| 一本色道久久88综合日韩精品 | 亚洲人AV永久一区二区三区久久| 丰满少妇人妻久久久久久| 精品久久久久成人码免费动漫| 国产精品久久久久乳精品爆| 久久久久亚洲av无码专区喷水| 一本一本久久aa综合精品| 久久久国产亚洲精品|