• <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>
            面對(duì)現(xiàn)實(shí),超越自己
            逆水行舟,不進(jìn)則退
            posts - 269,comments - 32,trackbacks - 0
            本文轉(zhuǎn)自:http://topic.csdn.net/t/20031208/15/2540422.html

            關(guān)于CString總結(jié)

            前言:串操作是編程中最常用也最基本的操作之一
             

                 做為VC程序員,無論是菜鳥或高手都曾用過CString.而且好像實(shí)際編程中很難離得開它(雖然它不是標(biāo)準(zhǔn)C++中的庫).因?yàn)镸FC中提供的這個(gè)類對(duì)我們操作字串實(shí)在太方便了,CString不僅提供各種豐富的操作函數(shù)、操作符重載,使我們使用起串起來更象basic中那樣直觀;而且它還提供了動(dòng)態(tài)內(nèi)存分配,使我們減少了多少字符串?dāng)?shù)組越界的隱患。但是,我們?cè)谑褂眠^程中也體會(huì)到CString簡直太容易出錯(cuò)了,而且有的不可捉摸。所以有許多高人站過來,建議拋棄它。
                    在此,我個(gè)人認(rèn)為:CString封裝得確實(shí)很完美,它有許多優(yōu)點(diǎn),如“容易使用   ,功能強(qiáng),動(dòng)態(tài)分配內(nèi)存,大量進(jìn)行拷貝時(shí)它很能節(jié)省內(nèi)存資源并且執(zhí)行效率高,與標(biāo)準(zhǔn)C完全兼容,同時(shí)支持多字節(jié)與寬字節(jié),由于有異常機(jī)制所以使用它安全方便”   其實(shí),使用過程中之所以容易出錯(cuò),那是因?yàn)槲覀儗?duì)它了解得還不夠,特別是它的實(shí)現(xiàn)機(jī)制。因?yàn)槲覀冎械拇蠖鄶?shù)人,在工作中并不愛那么深入地去看關(guān)于它的文檔,何況它還是英文的。  
                  由于前幾天我在工作中遇到了一個(gè)本不是問題但卻特別棘手、特別難解決而且莫名驚詫的問題。最后發(fā)現(xiàn)是由于CString引發(fā)的,后來,沒辦法,我把整個(gè)CString的實(shí)現(xiàn)全部看了一遍,才慌然大悟,并徹底弄清了問題的原因(這個(gè)問題,我已在csdn上開貼)。在此,我想把我的一些關(guān)于CString的知識(shí)總結(jié)一番,以供他(她)人借鑒,也許其中有我理解上的錯(cuò)誤,望發(fā)現(xiàn)者能通知我,不勝感謝。

            1   CString實(shí)現(xiàn)的機(jī)制 

                  CString是通過“引用”來管理串的,“引用”這個(gè)詞我相信大家并不陌生,象Window內(nèi)核對(duì)象、COM對(duì)象等都是通過引用來實(shí)現(xiàn)的。而CString也是通過這樣的機(jī)制來管理分配的內(nèi)存塊。實(shí)際上CString對(duì)象只有一個(gè)指針成員變量,所以任何CString實(shí)例的長度只有4字節(jié). 
                  即:   int   len   =   sizeof(CString);//len等于4
                 這個(gè)指針指向一個(gè)相關(guān)的引用內(nèi)存塊,如圖:   CString   str( "abcd ");
                                                                                                    ___
                      ____________                                                     |       |  
                    |                         |                                                   |       |  
                    |   0x04040404   |                                                   |       |     head部,為引用內(nèi)存塊相關(guān)信息
                    |____________|                                                   |       |
                              str                                                               |___|
                                                                                                  | 'a '|   0x40404040
                                                                                                  | 'b '|
                                                                                                  | 'c '|
                                                                                                  | 'd '|
                                                                                                  |   0   |

                正因?yàn)槿绱?,一個(gè)這樣的內(nèi)存塊可被多個(gè)CString所引用,例如下列代碼:
            1 CString   str( "abcd "); 
            2 CString   a   =   str; 
            3 CString   b(str); 
            4 CString   c; 
            5 c   =   b; 
                上面代碼的結(jié)果是:上面四個(gè)對(duì)象(str,a,b,c)中的成員變量指針有相同的值,都為0x40404040.而這塊內(nèi)存塊怎么知道有多少個(gè)CString引用它呢?同樣,它也會(huì)記錄一些信息。如被引用數(shù),串長度,分配內(nèi)存長度。
            這塊引用內(nèi)存塊的結(jié)構(gòu)定義如下:
            1 struct   CStringData 
            2 
            3     long   nRefs;               //表示有多少個(gè)CString   引用它.   4 
            4     int   nDataLength;     //串實(shí)際長度.   4 
            5     int   nAllocLength;   //總共分配的內(nèi)存長度(不計(jì)這頭部的12字節(jié)).   4 
            6 }; 
                 由于有了這些信息,CString就能正確地分配、管理、釋放引用內(nèi)存塊。
            如果你想在調(diào)試程序的時(shí)候獲得這些信息。可以在Watch窗口鍵入下列表達(dá)式:
            1 (CStringData*)((CStringData*)(this-> m_pchData)-1)或 
            2 (CStringData*)((CStringData*)(str.m_pchData)-1)//str為指CString實(shí)例
                正因?yàn)椴捎昧诉@樣的好機(jī)制,使得CString在大量拷貝時(shí),不僅效率高,而且分配內(nèi)存少。

            2   LPCTSTR   與   GetBuffer(int   nMinBufLength) 
             
                這兩個(gè)函數(shù)提供了與標(biāo)準(zhǔn)C的兼容轉(zhuǎn)換。在實(shí)際中使用頻率很高,但卻是最容易出錯(cuò)的地方。這兩個(gè)函數(shù)實(shí)際上返回的都是指針,但它們有何區(qū)別呢?以及調(diào)用它們后,幕后是做了怎樣的處理過程呢?
                (1)   LPCTSTR   它的執(zhí)行過程其實(shí)很簡單,只是返回引用內(nèi)存塊的串地址。   它是作為操作符重載提供的,
                        所以在代碼中有時(shí)可以隱式轉(zhuǎn)換,而有時(shí)卻需強(qiáng)制轉(zhuǎn)制。如:
            1                     CString   str; 
            2                     const   char*   p   =   (LPCTSTR)str; 
            3                     //假設(shè)有這樣的一個(gè)函數(shù),Test(const   char*   p);     你就可以這樣調(diào)用 
            4                     Test(str);//這里會(huì)隱式轉(zhuǎn)換為LPCTSTR 
                (2)   GetBuffer(int   nMinBufLength)   它類似,也會(huì)返回一個(gè)指針,不過它有點(diǎn)差別,返回的是LPTSTR
                (3)   這兩者到底有何不同呢?我想告訴大家,其本質(zhì)上完全不一樣,一般說LPCTSTR轉(zhuǎn)換后只應(yīng)該當(dāng)常量使用,或者做函數(shù)的入?yún)?;而GetBuffer(...)取出指針后,可以通過這個(gè)指針來修改里面的內(nèi)容,或者做函數(shù)的入?yún)?。為什么呢?也許經(jīng)常有這樣的代碼: 
                  
            1   CString   str( "abcd "); 
            2                 char*   p   =   (char*)(const   char*)str; 
            3                 p[2]   =   '';       
                其實(shí),也許有這樣的代碼后,你的程序并沒有錯(cuò),而且程序也運(yùn)行得挺好。但它卻是非常危險(xiǎn)的。再看 
                  
            1 CString   str( "abcd "); 
            2                 CString   test   =   str; 
            3                 
            4                 char*   p   =   (char*)(const   char*)str; 
            5                 p[2]   =   '';       
            6                 strcpy(p,   "akfjaksjfakfakfakj ");//這下完蛋了      
                       
                你知道此時(shí),test中的值是多少嗎?答案是 "abzd ".它也跟著改變了,這不是你所期望發(fā)生的。但為什么會(huì)這樣呢?你稍微想想就會(huì)明白,前面說過,因?yàn)镃String是指向引用塊的,str與test指向同一塊地方,當(dāng)你p[2]= 'z '后,當(dāng)然test也會(huì)隨著改變。所以用它做LPCTSTR做轉(zhuǎn)換后,你只能去讀這塊數(shù)據(jù),千萬別去改變它的內(nèi)容。 
                        
                假如我想直接通過指針去修改數(shù)據(jù)的話,那怎樣辦呢?就是用GetBuffer(...).看下述代碼: 
             
            1   CString   str( "abcd "); 
            2                 CString   test   =   str; 
            3                 
            4                 char*   p   =   str.GetBuffer(20); 
            5                 p[2]   =   '';     //       執(zhí)行到此,現(xiàn)在test中值卻仍是 "abcd " 
            6                 strcpy(p,   "akfjaksjfakfakfakj ");       //         執(zhí)行到此,現(xiàn)在test中值還是 "abcd " 
            7 
                為什么會(huì)這樣?其實(shí)GetBuffer(20)調(diào)用時(shí),它實(shí)際上另外建立了一塊新內(nèi)塊存,并分配20字節(jié)長度的buffer,而原來的內(nèi)存塊引用計(jì)數(shù)也相應(yīng)減1.     所以執(zhí)行代碼后str與test是指向了兩塊不同的地方,所以相安無事。

                (4)   不過這里還有一點(diǎn)注意事項(xiàng):就是str.GetBuffer(20)后,str的分配長度為20,即指針p它所指向的buffer只有20字節(jié)長,給它賦值時(shí),切不可超過,否則災(zāi)難離你不遠(yuǎn)了;如果指定長度小于原來串長度,如GetBuffer(1),實(shí)際上它會(huì)分配4個(gè)字節(jié)長度(即原來串長度);另外,當(dāng)調(diào)用GetBuffer(...)后并改變其內(nèi)容,一定要記得調(diào)用ReleaseBuffer(),這個(gè)函數(shù)會(huì)根據(jù)串內(nèi)容來更新引用內(nèi)存塊的頭部信息。 
                (5)   最后還有一注意事項(xiàng),看下述代碼: 
             1  char*   p   =   NULL; 
             2             const   char*   q   =   NULL; 
             3             { 
             4                     CString   str   =   "abcd "
             5                     q   =   (LPCTSTR)str; 
             6                     p   =   str.GetBuffer(20); 
             7                     AfxMessageBox(q);//   合法的 
             8                     strcpy(p,   "this   is   test ");//合法的, 
             9             } 
            10             AfxMessageBox(q);//   非法的,可能完蛋 
            11             strcpy(p,   "this   is   test ");//非法的,可能完蛋 
                這里要說的就是,當(dāng)返回這些指針后,   如果CString對(duì)象生命結(jié)束,這些指針也相應(yīng)無效。 
                下面演示一段代碼執(zhí)行過程          
             1   void   Test() 
             2       { 
             3           CString   str( "abcd ");//str指向一引用內(nèi)存塊(引用內(nèi)存塊的引用計(jì)數(shù)為1, 
             4                                                       長度為4,分配長度為4) 
             5           CString   a;//a指向一初始數(shù)據(jù)狀態(tài), 
             6           a   =   str;     //a與str指向同一引用內(nèi)存塊(引用內(nèi)存塊的引用計(jì)數(shù)為2, 
             7                                     長度為4,分配長度為4) 
             8           CString   b(a);//a、b與str指向同一引用內(nèi)存塊(引用內(nèi)存塊的引用 
             9                                       計(jì)數(shù)為3,長度為4,分配長度為4) 
            10           { 
            11                 LPCTSTR   temp   =   (LPCTSTR)a;//temp指向引用內(nèi)存塊的串首地址。 
            12                                                                     (引用內(nèi)存塊的引用計(jì)數(shù)為3,長度為4,分配長度為4) 
            13                 CString   d   =   a;   //a、b、d與str指向同一引用內(nèi)存塊(引用內(nèi)存塊的引用計(jì)數(shù)為4,                                                                 長度為4,分配長度為4) 
            14                 b   =   "testa ";   //這條語句實(shí)際是調(diào)用CString::operator=(CString&)函數(shù)。 
            15                                               b指向一新分配的引用內(nèi)存塊。(新分配的引用內(nèi)存塊的 
            16                                               引用計(jì)數(shù)為1,長度為5,分配長度為5) 
            17                                           //同時(shí)原引用內(nèi)存塊引用計(jì)數(shù)減1.   a、d與str仍指向原 
            18                                             引用內(nèi)存塊(引用內(nèi)存塊的引用計(jì)數(shù)為3,長度為4,分配長度為4)                                           
            19           }//由于d生命結(jié)束,調(diào)用析構(gòu)函數(shù),導(dǎo)至引用計(jì)數(shù)減1(引用內(nèi)存 
            20               塊的引用計(jì)數(shù)為2,長度為4,分配長度為4) 
            21           LPTSTR   temp   =   a.GetBuffer(10);//此語句也會(huì)導(dǎo)致重新分配新內(nèi)存塊。 
            22                                                                       temp指向新分配引用內(nèi)存塊的串首地址(新 
            23                                                                       分配的引用內(nèi)存塊的引用計(jì)數(shù)為1,長度 
            24                                                                       為0,分配長度為10) 
            25                                                                       //同時(shí)原引用內(nèi)存塊引用計(jì)數(shù)減1.   只有str仍 
            26                                                                           指向原引用內(nèi)存塊(引用內(nèi)存塊的引用計(jì)數(shù)為1, 
            27                                                                           長度為4,分配長度為4)                                             
            28           strcpy(temp,   "temp ");     //a指向的引用內(nèi)存塊的引用計(jì)數(shù)為1,長度為0,分配長度為10 
            29           a.ReleaseBuffer();//注意:a指向的引用內(nèi)存塊的引用計(jì)數(shù)為1,長度為4,分配長度為10 
            30       } 
            31       //執(zhí)行到此,所有的局部變量生命周期都已結(jié)束。對(duì)象str   a   b   各自調(diào)用自己的析構(gòu)構(gòu) 
            32       //函數(shù),所指向的引用內(nèi)存塊也相應(yīng)減1 
            33       //注意,str   a   b   所分別指向的引用內(nèi)存塊的計(jì)數(shù)均為0,這導(dǎo)致所分配的內(nèi)存塊釋放 

                 通過觀察上面執(zhí)行過程,我們會(huì)發(fā)現(xiàn)CString雖然可以多個(gè)對(duì)象指向同一引用內(nèi)塊存,但是它們?cè)谶M(jìn)行各種拷貝、賦值及改變串內(nèi)容時(shí),它的處理是很智能并且非常安全的,完全做到了互不干涉、互不影響。當(dāng)然必須要求你的代碼使用正確恰當(dāng),特別是實(shí)際使用中會(huì)有更復(fù)雜的情況,如做函數(shù)參數(shù)、引用、及有時(shí)需保存到CStringList當(dāng)中,如果哪怕有一小塊地方使用不當(dāng),其結(jié)果也會(huì)導(dǎo)致發(fā)生不可預(yù)知的錯(cuò)誤 

            3     FreeExtra()的作用

                 看這段代碼 
            1 CString   str( "test "); 
            2 LPTSTR   temp   =   str.GetBuffer(50); 
            3 strcpy(temp,   "there   are   22   character "); 
            4 str.ReleaseBuffer(); 
            5 str.FreeExtra(); 

                 上面代碼執(zhí)行到第(4)行時(shí),大家都知道str指向的引用內(nèi)存塊計(jì)數(shù)為1,長度為22,分配長度為50.   那么執(zhí)行str.FreeExtra()時(shí),它會(huì)釋放所分配的多余的內(nèi)存。(引用內(nèi)存塊計(jì)數(shù)為1,長度為22,分配長度為22) 

            4     Format(...)     與   FormatV(...) 

                 這條語句在使用中是最容易出錯(cuò)的。因?yàn)樗罡挥屑记尚?,也相?dāng)靈活。在這里,我沒打算對(duì)它細(xì)細(xì)分析,實(shí)際上sprintf(...)怎么用,它就怎么用。我只提醒使用時(shí)需注意一點(diǎn):就是它的參數(shù)的特殊性,由于編譯器在編譯時(shí)并不能去校驗(yàn)格式串參數(shù)與對(duì)應(yīng)的變?cè)念愋图伴L度。所以你必須要注意,兩者一定要對(duì)應(yīng)上, 
                 否則就會(huì)出錯(cuò)。如:
            1  CString   str; 
            2       int   a   =   12
            3       str.Format( "first:%l,   second:   %s ",   a,   "error ");//result?試試
             
            5     LockBuffer()   與   UnlockBuffer()
             

                  顧名思議,這兩個(gè)函數(shù)的作用就是對(duì)引用內(nèi)存塊進(jìn)行加鎖及解鎖。
                  但使用它有什么作用及執(zhí)行過它后對(duì)CString串有什么實(shí)質(zhì)上的影響。其實(shí)挺簡單,看下面代碼:
            1 CString   str( "test "); 
            2 str.LockBuffer(); 
            3 CString   temp   =   str; 
            4 str.UnlockBuffer(); 
            5 str.LockBuffer(); 
            6 str   =   "error "
            7 str.ReleaseBuffer(); 
            8 
                  執(zhí)行完(3)后,與通常情況下不同,temp與str并不指向同一引用內(nèi)存塊。你可以在watch窗口用這個(gè)表達(dá)式(CStringData*)((CStringData*)(str.m_pchData)-1)看看。
                  其實(shí)在msdn中有說明: 
                   While   in   a   locked   state,   the   string   is   protected   in   two   ways:   
                   No   other   string   can   get   a   reference   to   the   data   in   the   locked   string,   even   if   that   string   is   assigned   to   the   locked   string. 
                   The   locked   string   will   never   reference   another   string,   even   if   that   other   string   is   copied   to   the   locked   string.   

            6     CString   只是處理串嗎?
             
                 不對(duì),CString不只是能操作串,而且還能處理內(nèi)存塊數(shù)據(jù)。功能完善吧!看這段代碼
            1 char     p[20]; 
            2 for(int   loop=0;   loop <sizeof(p);   loop++
            3 
            4 p[loop]   =   10-loop; 
            5 
            6 CString   str((LPCTSTR)p,   20); 
            7 char   temp[20]; 
            8 memcpy(temp,   str,   str.GetLength()); 
                  str完全能夠轉(zhuǎn)載內(nèi)存塊p到內(nèi)存塊temp中。所以能用CString來處理二進(jìn)制數(shù)據(jù) 

            7     AllocSysString()與SetSysString(BSTR*)  
             
                  這兩個(gè)函數(shù)提供了串與BSTR的轉(zhuǎn)換。使用時(shí)須注意一點(diǎn):當(dāng)調(diào)用AllocSysString()后,須調(diào)用它SysFreeString(...)   

            8     參數(shù)的安全檢驗(yàn) 

                  在MFC中提供了多個(gè)宏來進(jìn)行參數(shù)的安全檢查,如:ASSERT.     其中在CString中也不例外,有許多這樣的參數(shù)檢驗(yàn),其實(shí)這也說明了代碼的安全性高,可有時(shí)我們會(huì)發(fā)現(xiàn)這很煩,也導(dǎo)致Debug與Release版本不一樣,如有時(shí)程序Debug通正常,而Release則程序崩潰;而有時(shí)恰相反,Debug不行,Release行。其實(shí)我個(gè)人認(rèn)為,我們對(duì)CString的使用過程中,應(yīng)力求代碼質(zhì)量高,不能在Debug版本中出現(xiàn)任何斷言框,哪怕release運(yùn)行似乎看起來一切正常。但很不安全。如下代碼:
             
            1 CString   str( "test "); 
            2 str.LockBuffer(); 
            3 LPTSTR   temp   =   str.GetBuffer(10); 
            4 strcpy(temp,   "error "); 
            5 str.ReleaseBuffer(); 
            6 str.ReleaseBuffer();//執(zhí)行到此時(shí),Debug版本會(huì)彈出錯(cuò)框
                
            9   CString的異常處理 

                  我只想強(qiáng)調(diào)一點(diǎn):只有分配內(nèi)存時(shí),才有可能導(dǎo)致拋出CMemoryException.
                  同樣,在msdn中的函數(shù)聲明中,注有throw(   CMemoryException)的函數(shù)都有重新分配或調(diào)整內(nèi)存的可能。
             
            10   跨模塊時(shí)的CString

                即一個(gè)DLL的接口函數(shù)中的參數(shù)為CString&時(shí),它會(huì)發(fā)生怎樣的現(xiàn)象。解答我遇到的 
                問題。我的問題原來已經(jīng)發(fā)貼,地址為:http://www.csdn.net/expert/topic/741/741921.xml?temp=.2283136 

                構(gòu)造一個(gè)這樣CString對(duì)象時(shí),如CString   str,你可知道此時(shí)的str所指向的引用內(nèi)存塊嗎?也許你會(huì)認(rèn)為它指向NULL。其實(shí)不對(duì),如果這樣的話,CString所采用的引用機(jī)制管理內(nèi)存塊就會(huì)有麻煩了,所以CString在構(gòu)造一個(gè)空串的對(duì)象時(shí),它會(huì)指向一個(gè)固定的初始化地址,這塊數(shù)據(jù)的聲明如下:
                  AFX_STATIC_DATA   int   _afxInitData[]   =   {-1,0,0,0};
                簡要描述概括一下:當(dāng)某個(gè)CString對(duì)象串置空的話,如Empty(),CString   a等,它的成員變量m_pchData就會(huì)指向_afxInitData這個(gè)變量的地址。當(dāng)這個(gè)CString對(duì)象生命周期結(jié)束時(shí),正常情況下它會(huì)去對(duì)所指向的引用內(nèi)存塊計(jì)數(shù)減1,如果引用計(jì)數(shù)為0(即沒有任何CString引用時(shí)),則釋放這塊引用內(nèi)存。而現(xiàn)在的情況是如果CString所指向的引用內(nèi)存塊是初始化內(nèi)存塊時(shí),則不會(huì)釋放任何內(nèi)存。

                說了這么多,這與我遇到的問題有什么關(guān)系呢?其實(shí)關(guān)系大著呢?其真正原因就是如果exe模塊與dll模塊有一
                個(gè)是static編譯連接的話。那么這個(gè)CString初始化數(shù)據(jù)在exe模塊與dll模塊中有不同的地址,因?yàn)閟tatic連接則會(huì)在本模塊中有一份源代碼的拷貝。另外一種情況,如果兩個(gè)模塊都是share連接的,CString的實(shí)現(xiàn)代碼則在另一個(gè)單獨(dú)的dll實(shí)現(xiàn),而AFX_STATIC_DATA指定變量只裝一次,所以兩個(gè)模塊中_afxInitData有相同的地址。 
                現(xiàn)在問題完全明白了吧!你可以自己去演示一下。 
             
            1     __declspec   (dllexport)   void   test(CString&   str) 
            2     { 
            3         str   =   "abdefakdfj ";//如果是static連接,并且傳入的str為空串的話,這里出錯(cuò)。 
            4     }
             
                最后一點(diǎn)想法:寫得這里,其實(shí)CString中還有許多技巧性的好東東,我并沒去解釋。如很多重載的操作符、查找等。我認(rèn)為還是詳細(xì)看看msdn,這樣會(huì)比我講好多了。我只側(cè)重那些情況下會(huì)可能出錯(cuò)。當(dāng)然,我敘述如有錯(cuò)誤,敬請(qǐng)高手指點(diǎn),不勝感謝!

            sorry,改正一下 
                 看起來一切正常。但很不安全。如下代碼:  
            1 CString   str( "test "); 
            2 str.LockBuffer(); 
            3 LPTSTR   temp   =   str.GetBuffer(10); 
            4 strcpy(temp,   "error "); 
            5 str.ReleaseBuffer(); 
            6 str.UnlockBuffer();//執(zhí)行到此時(shí),Debug版本會(huì)彈出錯(cuò)框 
            posted on 2012-04-28 09:53 王海光 閱讀(489) 評(píng)論(0)  編輯 收藏 引用 所屬分類: MFC
            精品无码久久久久国产动漫3d| 色综合久久综合网观看| 中文字幕日本人妻久久久免费| 波多野结衣中文字幕久久 | 99久久精品午夜一区二区| 9191精品国产免费久久| 久久亚洲sm情趣捆绑调教| 国产精品青草久久久久婷婷| 欧美性大战久久久久久| 久久99国产综合精品免费| 久久人人超碰精品CAOPOREN| 精品无码久久久久国产| 色播久久人人爽人人爽人人片aV| 97久久精品无码一区二区| 女同久久| 久久精品成人一区二区三区| 国产精品美女久久久久| 一本色道久久综合狠狠躁| 午夜精品久久久久久久无码| 日韩欧美亚洲综合久久影院d3| 久久亚洲精品人成综合网| 伊人久久大香线焦AV综合影院 | 99精品久久精品一区二区| 久久久久国产精品麻豆AR影院| 久久福利青草精品资源站免费| 久久综合噜噜激激的五月天| 久久人人爽人人人人爽AV| 伊色综合久久之综合久久| 久久久黄片| 久久久久国产日韩精品网站| 中文字幕亚洲综合久久| 青青国产成人久久91网 | 亚洲国产精品无码久久久蜜芽| 久久精品无码av| 精品久久人人爽天天玩人人妻| 99国内精品久久久久久久 | 精品国际久久久久999波多野 | 国产精自产拍久久久久久蜜| 99久久久久| 国产午夜精品久久久久九九电影| 久久国产高清字幕中文|