• <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>
            posts - 15,comments - 21,trackbacks - 0
            很久沒有碰C++,下個項目要開始使用C++,所以很多東西需要撿起來重新看看。從今天起記錄一些筆記,方便自己今后查閱。言歸正傳,先從構(gòu)造函數(shù)的初始化列表說起。我把這個知識點細(xì)化成3個問題,1.為什么要有初始化列表,它和構(gòu)造函數(shù)中初始化有什么不一樣。2.初始化的順序。3.一些注意的細(xì)節(jié)。
                  先說第一個問題。我們有兩個東西,是必須在初始化列表里完成的,一個是const修飾的變量,一個是引用。這點我就不細(xì)說了,查閱資料的都可以找到。下面我具體說說類成員。
            class Test1
            {
            public:
            Test1()
            {
            cout << "Test1 default constructor" << endl;
            }
            Test1(int i)
            {
            cout << "Test1 value constructor" << endl;
            }
            Test1(const Test1 &obj)
            {
            cout << "Test1 copy constructor" << endl;
            }
            Test1& operator = (const Test1 &obj)
            {
            cout << "Test1 = constructor" << endl;
            return *this;
            }
            ~Test1()
            {
            cout << "Test1 destructor" << endl;
            }
            };
             我定義一個類,然后再定義一個類,其中包含Test1
            class Test2
            {
            public:
                Test2()
                {
                    t1 = Test1(1);
                }

            private:
                Test1 t1;
            }; 
            我們在構(gòu)造函數(shù)中初始化Test1,我們看看運行結(jié)果
            Test1 default constructor
            Test1 value constructor
            Test1 = constructor
            Test1 destructor
            Test1 destructor
            我們分析下這個輸出。Test1 default constructor,這說明在進入Test1構(gòu)造函數(shù)之前,已經(jīng)初始化了t1成員,并且調(diào)用的是無參構(gòu)造函數(shù)。Test1 value constructor這個是Test1(1)創(chuàng)建出來的對象。Test1 = constructor,這個表示條用了拷貝構(gòu)造函數(shù),Test1 destructor這個表示Test1(1)這個臨時對象的析構(gòu),Test1 destructor這個表示是t1這個成員對象的析構(gòu)。從上面的結(jié)果來看,構(gòu)造函數(shù)中t1 = Test1(1);其實并不是真正意義是上的初始化,而是一次拷貝賦值。當(dāng)進入構(gòu)造函數(shù)內(nèi)部之前,類成員會被默認(rèn)構(gòu)造函數(shù)初始化。如果說Test1是個很大的對象,這塊會造成性能上的開銷。所以,這點也是使用初始化列表的原因之一。
                  第二我們再來說下順序問題。簡單的原則是初始化列表里的會先于構(gòu)造函數(shù)中,初始化列表里會按照變量聲明的順序。我們具體看看下面的例子。
            class Test3()
            {
            public:
                Test3(
            int x,int y,int z):_z(z),_y(y)
                {
                    _x 
            = x;
                }

            private:
                
            int _x,_y,_z;
            };
            按照上面的說法,賦值的順序是_y,_z,_x。
                  第三個是注意問題,每個成員只能在初始化列表里出現(xiàn)一次。
            class Test3
            {
            public:
                Test3(
            int x,int y,int z):_z(z),_y(y),_z(x)
                {
                    _x 
            = x;
                }

            private:
                
            int _x,_y,_z;
            };
            比如這種就是問題的。_z被初始化了2次。
            posted @ 2012-08-14 10:24 梨樹陽光 閱讀(1482) | 評論 (3)編輯 收藏
                  寫服務(wù)器的,通常會涉及到內(nèi)存池的東西,自己在這方面也看了寫了一些東西,有些體會,寫出來跟大家分享下。
                  內(nèi)存池基本包含以下幾個東西,第一,初始化。第二,分配內(nèi)存。第三,回收內(nèi)存。所謂初始化,就是在服務(wù)器啟動的時候,或者第一次需要內(nèi)存的時候,系統(tǒng)分配很大的一塊內(nèi)存,方便之后的使用。分配內(nèi)存,就是從內(nèi)存池中取出需要的內(nèi)存給外部使用,當(dāng)然這里需要考慮的是當(dāng)內(nèi)存池中沒有內(nèi)存可分配時候的處理。回收內(nèi)存,簡單來說,就是外面對象生命期結(jié)束了,將分配出去的內(nèi)存回收入內(nèi)存池中。好了簡單概念就說完了,我們先來看一種最簡單的設(shè)計方式。
            //為了方便描述,這里附上幾個簡單的鏈表操作宏
            #define INSERT_TO_LIST( head, item, prev, next ) \
            do{ \
            if ( head ) \
            (head)->prev = (item); \
            (item)->next = (head); \
            (head) = (item);          \
            }while(0)
            #define REMOVE_FROM_LIST(head, item, prev, next) \
            do{ \
            if ( (head) == (item) ) \
            { \
            (head) = (item)->next; \
            if ( head ) \
            (head)->prev = NULL; \
            } \
            else \
            { \
            if ( (item)->prev ) \
            (item)->prev->next = (item)->next;          \
            \
            if ( (item)->next ) \
            (item)->next->prev = (item)->prev;          \
            } \
            }while(0)
            struct student
            {
                  char name[32];
                  byte sex;
                  
                  struct student *prev,*next;
            };

            static struct mem_pool
            {
                  //該指針用來記錄空閑節(jié)點
                  
            struct student *free;
                  //該變量記錄分配結(jié)點個數(shù)
                  size_t alloc_cnt;
            }s_mem_pool;

            //分配內(nèi)存“塊”的函數(shù)
            bool mem_pool_resize(size_t size)
            {
                  //該函數(shù)創(chuàng)建size個不連續(xù)的對象,把他們通過鏈表的方式加入到s_mem_pool.free中
                  for ( size_t i = 0;i < size;++i )
                  {
                        
            struct student *p = (struct student *)malloc(sizeof(struct student));
                        
            if ( !p )
                           return false;
                        
                        p->prev = p->next = NULL;
                        INSERT_TO_LIST(s_mem_pool.free,p,prev,next);

                  }

                  s_mem_pool.alloc_cnt += size;
            }

            #define MEM_INIT_SIZE 512  
            #define MEM_INC_SIZE 256
            //初始化函數(shù)
            bool mem_pool_init()
            {
            if ( !mem_pool_resize(MEM_INIT_SIZE) )
                        return false;
            return true;
            }
            struct student *get_data()
            {
            if ( s_mem_pool.free == NULL )
            {
                        if ( !mem_pool_resize(MEM_INC_SIZE) )
                              return NULL;
            }
            struct student *ret = s_mem_pool.free;
            REMOVE_FROM_LIST(s_mem_pool.free,ret,prev,next)
            return ret;
            }
            void free_data(struct student *p)
            {
            if ( !p )
                        return;
            memset(p,0,sizeof(struct student));
            INSERT_TO_LIST(s_mem_pool.free,p,prev,next)
            }
            好了最簡單的內(nèi)存池的大致框架就是這樣。我們先來看下他的過程。首先,在mem_pool_init()函數(shù)中,他先分配512個不連續(xù)的student對象。每分配出來一個就把它加入到free鏈表中,初始化完成后內(nèi)存池大概是這樣的

            接下來就是從內(nèi)存池中取出一個對象get_data()。函數(shù)先去判斷是否有空閑的對象,有則直接分配,否則再向系統(tǒng)獲取一"塊"大的內(nèi)存。調(diào)用一次后的內(nèi)存池大概是這樣的

            釋放對象,再把對象加入到Free鏈表中。
            以上就是過程的簡單分析,下面我們來看看他的缺點。
            第一,內(nèi)存不是連續(xù)的,容易產(chǎn)生碎片
            第二,一個類型就得寫一個這樣的內(nèi)存池,很麻煩
            第三,為了構(gòu)建這個內(nèi)存池,每個沒對象必須加上一個prev,next指針
            好了,我們來優(yōu)化一下它。我們重新定義下我們的結(jié)構(gòu)體
            union student
            {
                
            int index;
                
            struct
                {
                    
            char name[32];
                    
            byte sex;
                }s;
            };

            static struct mem_pool
            {
                
            //該下標(biāo)用來記錄空閑節(jié)點
                int free;
                
            //內(nèi)存池
                union student *mem;
                
            //已分配結(jié)點個數(shù)
                size_t alloc_cnt;
            }s_mem_pool;

            //分配內(nèi)存塊的函數(shù)
            bool mem_pool_resize(size_t size)
            {
                size_t new_size 
            = s_mem_pool.alloc_cnt+size;
                union student 
            *tmp = (union student *)realloc(s_mem_pool.mem,new_size*sizeof(union student));
                
            if ( !tmp )
                    
            return false;
                    
                memset(tmp
            +s_mem_pool.alloc_cnt,0,size*sizeof(union student));
                size_t i 
            = s_mem_pool.alloc_cnt;
                
            for ( ;i < new_size - 1;++i )
                {
                    tmp[i].index 
            = i + 1;
                }
                
                tmp[i].index 
            = -1;
                s_mem_pool.free 
            = s_mem_pool.alloc_cnt;
                s_mem_pool.mem 
            = tmp;
                s_mem_pool.alloc_cnt 
            = new_size;
                
                
            return true;
            }

            #define MEM_INIT_SIZE    512  
            #define MEM_INC_SIZE    256
            //初始化函數(shù)
            bool mem_pool_init()
            {
                
            if ( !mem_pool_resize(MEM_INIT_SIZE) )
                    
            return false;
                    
                
            return true;
            }

            union student 
            *get_data()
            {
                
            if ( s_mem_pool.free == -1 )
                {
                    
            if ( !mem_pool_resize(MEM_INC_SIZE) )
                        
            return NULL;
                }
                
                union student 
            *ret = s_mem_pool.mem+s_mem_pool.free;
                s_mem_pool.free 
            = ret->index;
                
            return ret;
            }

            void free_data(union student *p)
            {
                
            if ( !p )
                    
            return;
                
                p
            ->index = s_mem_pool.free;
                s_mem_pool.free 
            = p - s_mem_pool.mem;
            }
            我們來看看改進了些什么。第一student改成了聯(lián)合體,這主要是為了不占用額外的內(nèi)存,也就是我們上面所說的第三個缺點,第二,我們使用了realloc函數(shù),這樣我們可以使我們分配出來的內(nèi)存是連續(xù)的。我們初始化的時候多了一個for循環(huán),這是為了記錄空閑對象的下標(biāo),當(dāng)我們?nèi)〕鲆粋€對象時,free可以立刻知道下一個空閑對象的位置,釋放的時候,對象先記錄free此時的值,接著再把free賦值成該對象在數(shù)組的下標(biāo),這樣就完成了回收工作。
            我們繼續(xù)分析這段代碼,問題在realloc函數(shù)上,如果我們的s_mem_pool.mem已經(jīng)很大了,在realloc的時候我們都知道,先要把原來的數(shù)據(jù)做一次拷貝,所以如果數(shù)據(jù)量很大的情況下做一次拷貝,是會消耗性能的。那這里有沒有好的辦法呢,我們進一步優(yōu)化
            思路大概是這樣
            初始化

            再次分配的時候,我們只需要重新分配新的內(nèi)存單元,而不需要拷貝之前的內(nèi)存單元。

            因此基于此思路,我們修改我們的代碼
            #include <stdio.h>
            #include 
            <stdlib.h>

            struct student
            {
                
            int index;

                
            char name[32];
                
            byte sex;
            };

            static struct mem_pool
            {
                
            //該下標(biāo)用來記錄空閑節(jié)點
                int free;
                
            //內(nèi)存池
                struct student **mem;
                
            //已分配塊個數(shù)
                size_t block_cnt;
            }s_mem_pool;

            #define BLOCK_SIZE        256        //每塊的大小
            //分配內(nèi)存塊的函數(shù)
            bool mem_pool_resize(size_t block_size)
            {
                size_t new_cnt 
            = s_mem_pool.block_cnt + block_size;
                
            struct student **tmp = (struct student **)realloc(s_mem_pool.mem,new_size*sizeof(struct student *));
                
            if ( !tmp )
                    
            return false;
                    
                memset(tmp
            +s_mem_pool.block_cnt,0,size*sizeof(struct student*));
                
            for ( size_t i = s_mem_pool.block_cnt;i < new_cnt;++i )
                {
                    tmp[i] 
            = (struct student *)calloc(BLOCK_SIZE,sizeof(struct student));
                    
            if ( !tmp[i] )
                        
            return false;
                        
                    size_t j 
            = 0;
                    
            for(;j < BLOCK_SIZE - 1;++j )
                    {
                        tmp[i][j].index 
            = i*BLOCK_SIZE+j+1;
                    }
                    
                    
            if ( i != new_cnt-1 )
                        tmp[i][j].index 
            = (i+1)*BLOCK_SIZE;
                    
            else
                        tmp[i][j].index 
            = -1;
                }
                
                s_mem_pool.free 
            = s_mem_pool.alloc_cnt*BLOCK_SIZE;
                s_mem_pool.mem 
            = tmp;
                s_mem_pool.block_cnt 
            = new_cnt;
                
                
            return true;
            }
             
            #define MEM_INC_SIZE    10
            //初始化函數(shù)
            bool mem_pool_init()
            {
                
            if ( !mem_pool_resize(MEM_INIT_SIZE) )
                    
            return false;
                    
                
            return true;
            }

            struct student *get_data()
            {
                
            if ( s_mem_pool.free == -1 )
                {
                    
            if ( !mem_pool_resize(MEM_INC_SIZE) )
                        
            return NULL;
                }
                
                
            struct student *ret = s_mem_pool.mem[s_mem_pool.free/BLOCK_SIZE]+s_mem_pool.free%BLOCK_SIZE;
                
            int pos = s_mem_pool.free;
                s_mem_pool.free 
            = ret->index;
                ret
            ->index = pos;
                
            return ret;
            }

            void free_data(struct student *p)
            {
                
            if ( !p )
                    
            return;
                
                
            int pos = p->index;
                p
            ->index = s_mem_pool.free;
                s_mem_pool.free 
            = pos;
            }
            這里不一樣的地方主要在mem_pool_resize函數(shù)中,mem變成了2級指針,每次realloc的時候只需要分配指針數(shù)組的大小,無須拷貝對象,這樣可以提高效率,但是為了在釋放的時候把對象放回該放的位置,我們這里在結(jié)構(gòu)體里加入了index變量,記錄它的下標(biāo)。在內(nèi)存池里,它表示下個空閑對象的下標(biāo),在內(nèi)存池外,它表示在內(nèi)存池中的下標(biāo)。總的來說滿足了一個需求,卻又帶來了新的問題,有沒有更好的方法呢,答案是肯定,不過今天先寫到這里,明天繼續(xù)。
            posted @ 2012-07-19 11:41 梨樹陽光 閱讀(3546) | 評論 (2)編輯 收藏
                  昨天在看一篇文章的時候,突然想起了這個基礎(chǔ)性的問題,自己一直對它的區(qū)別不是很清楚,于是今天上午研究下了,分享下自己的理解。(對它很清楚的同學(xué)們可以略過此篇文章)
                  從存儲方式來說,文件在磁盤上的存儲方式都是二進制形式,所以,文本文件其實也應(yīng)該算二進制文件。那么他們的區(qū)別呢,各自的優(yōu)缺點呢?不急,我慢慢道來。
                  先從他們的區(qū)別來說,雖然都是二進制文件,但是二進制代表的意思不一樣。打個比方,一個人,我們可以叫他的大名,可以叫他的小名,但其實都是代表這個人。二進制讀寫是將內(nèi)存里面的數(shù)據(jù)直接讀寫入文本中,而文本呢,則是將數(shù)據(jù)先轉(zhuǎn)換成了字符串,再寫入到文本中。下面我用個例子來說明。
            我們定義了一個結(jié)構(gòu)體,表示一個學(xué)生信息,我們打算把學(xué)生的信息分別用二進制和文本的方式寫入到文件中。
            struct Student 
            {
                
            int num;
                
            char name[20];
                
            float score;
            };
            我們定義兩個方法,分別表示內(nèi)存寫入和文本寫入
            //使用二進制寫入
            void write_to_binary_file()
            {
                
            struct Student stdu;
                stdu.num 
            = 111;
                sprintf_s(stdu.name,
            20,"%s","shine");
                stdu.score 
            = 80.0f;
                fstream binary_file(
            "test1.dat",ios::out|ios::binary|ios::app); //此處省略文件是否打開失敗的判斷
                binary_file.write((char *)&stdu,sizeof(struct Student));//二進制寫入的方式
                binary_file.close();

            //文本格式寫入
            void write_to_text_file()
            {
                
            struct Student stdu;
                stdu.num 
            = 111;
                sprintf_s(stdu.name,
            20,"%s","shine");
                stdu.score 
            = 80.0f;
                FILE 
            *fp = fopen("test2.dat","a+");   //此處省略文件是否打開失敗的判斷
                fprintf(fp,"%d%s%f",stdu.num,stdu.name,stdu.score); //將數(shù)據(jù)轉(zhuǎn)換成字符串(字符串的格式可以自己定義)
                fclose(fp);

            //MAIN函數(shù)調(diào)用前面兩個方法
            int _tmain(int argc, _TCHAR* argv[])
            {
                write_to_binary_file();
                write_to_text_file();
                
                
            return 0;
            }
            我們來看下,文件里面的格式 2進制文件

            文本文件


            2進制文件里面將111編碼成6F,1個字節(jié),這剛好是111的16進制表示,而文本文件中則寫成31,31,31用了3個字節(jié),表示111。73   68   69   6E   65 表示shine,之后2進制文件里是幾個連續(xù)的FE,而文本文件中是38   30......文本文件將浮點數(shù)80.000000用了38(表示8)   30(表示0)  2E(表示.)   30(表示0)   30(表示0)   30(表示0)   30(表示0)   30(表示0)   30(表示0),二進制文件用了4個字節(jié)表示浮點數(shù)00   00   A0   42
            通過這里我們可以初見端倪了,二進制將數(shù)據(jù)在內(nèi)存中的樣子原封不動的搬到文件中,文本格式則是將每一個數(shù)據(jù)轉(zhuǎn)換成字符寫入到文件中,他們在大小上,布局上都有著區(qū)別。由此可以看出,2進制文件可以從讀出來直接用,但是文本文件還多一個“翻譯”的過程,因此2進制文件的可移植性好。
            posted @ 2012-07-12 09:59 梨樹陽光 閱讀(13049) | 評論 (5)編輯 收藏

            先看一個簡單的使用例子

            求任意個自然數(shù)的平方和:

            int SqSum(int n,)   
            {   
                va_list arg_ptr;   
                
            int sum = 0,_n = n;   
                arg_ptr 
            = va_start(arg_ptr,n);   
                
            while(_n != 0)   
                {   
                    sum 
            += (_n*_n);   
                    _n 
            = va_arg(arg_ptr,int);   
                }   
                va_end(arg_ptr);   
                
            return sum;   
            }
            首先解釋下函數(shù)參數(shù)入棧情況 在VC等絕大多數(shù)C編譯器中,默認(rèn)情況下,參數(shù)進棧的順序是由右向左的,因此,參數(shù)進棧以后的內(nèi)存模型如下圖所示:
            最后一個固定參數(shù)的地址位于第一個可變參數(shù)之下,并且是連續(xù)存儲的。
            | 最后一個可變參數(shù)(高內(nèi)存地址處) | 第N個可變參數(shù) | 第一個可變參數(shù) | 最后一個固定參數(shù) | 第一個固定參數(shù)(低內(nèi)存地址處)
            明白上面那個順序,就知道其實可變參數(shù)就是玩弄參數(shù)的地址,已達(dá)到“不定”的目的 下面我摘自VC中的源碼來解釋
            va_list,va_start,va_arg,va_end宏
            1.其實va_list就是我們平時經(jīng)常用的char* typedef char * va_list;
            2.va_start該宏的目的就是將指針指向最后一個固定參數(shù)的后面,即第一個不定參數(shù)的起始地址 #define va_start(ap,v)( ap = (va_list)&v + _INTSIZEOF(v) ) v即表示最后一個固定參數(shù),&v表示v的地址, #define _INTSIZEOF(n) ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) ) 該宏其實是一個內(nèi)存對齊的操作。即表示大于sizeof(n)且為sizeof(int)倍數(shù)的最小整數(shù)。這句話有點繞,其實舉幾個例子就簡單了。比如1--4,則返回4,5--8則返回8
            3.va_arg 該宏的目的是將ap指針繼續(xù)后移,讀取后面的參數(shù),t表示參數(shù)類型。該宏首先將ap指針移動到下一個參數(shù)的起始地址ap += _INTSIZEOF(t),然后將本參數(shù)的值返回 #define va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )
            4.va_end將指針賦空 #define va_end(ap) ap = (va_list)0 有了這個分析我們可以把上例中的代碼重新翻譯下
            int SqSum(int n,)   
            {   
                
            char *arg_ptr;   
                
            int sum = 0,_n = n;   
                arg_ptr 
            = (char *)&+ 4;//本機上sizeof(int) = 4   
                while(_n != 0)   
                {   
                    sum 
            += (_n*_n);   
                    arg_ptr 
            += 4;   
                    _n 
            = *(int *)(arg_ptr-4);   
                }   
                arg_ptr 
            = (void*)0;   
            }  
            這樣我們也可以寫出我們自己的printf了
            posted @ 2012-07-12 09:51 梨樹陽光 閱讀(1066) | 評論 (1)編輯 收藏

            1.制作自己的動態(tài)庫和靜態(tài)庫

            linux下動態(tài)庫以.so結(jié)尾,靜態(tài)庫以.a結(jié)尾,它們都以lib開頭,比如一個庫名為net,那么它的全名應(yīng)該是libnet.so或者libnet.a

            我們有兩個文件,hello.ctest.c,下面是兩個文件的內(nèi)容

            //hello.c

            #include <stdio.h>

             

            void my_lib_func()

            {

            printf("Library routine called\r\n");

            }

             

            //test.c

            #include <stdio.h>

             

            int main()

            {

            my_lib_func();

             

            return 1;

            }

             

            test.c調(diào)用了hello.c的方法,我們把hello.c封裝成庫文件。無論是靜態(tài)庫還是動態(tài)庫,都是由.o文件組成,我們先把gcc -c hello.c生成.o文件

            制作靜態(tài)庫

            ar crv libmyhello.a hello.o,ar是生成靜態(tài)庫的命令,libmyhello.a是我的靜態(tài)庫名。下一步就是在我的程序中使用靜態(tài)庫

            可以看到已經(jīng)有了Library routine called的結(jié)果,說明調(diào)用成功了。

            下面我們刪除libmyhello.a,看看程序是否還是運行正常


            我們發(fā)現(xiàn)程序依然運行正常,說明靜態(tài)庫已經(jīng)連接進入我們的程序中

            制作動態(tài)庫


            我們看見動態(tài)庫libmyhello.so已經(jīng)生成,下面繼續(xù)使用


            找不到庫文件,這個時候我們把so文件拷貝到/usr/lib下面


            運行成功

             

            2.動態(tài)庫和靜態(tài)庫同時存在的調(diào)用規(guī)則

            我們可以發(fā)現(xiàn),不論是動態(tài)庫還是靜態(tài)庫,程序編譯連接的時候都是加的參數(shù)-l,那么當(dāng)他們同時存在的時候,程序會選擇動態(tài)庫還是靜態(tài)庫呢。我們做個嘗試。


            我們同時存在libmyhello.alibmyhello.so,我們發(fā)現(xiàn)運行的時候,出現(xiàn)找不到動態(tài)庫的錯誤,由此,我們可以得出結(jié)論,同時存在動態(tài)庫和靜態(tài)庫的時候,gcc會優(yōu)先選擇動態(tài)庫

            posted @ 2012-07-11 15:15 梨樹陽光 閱讀(1510) | 評論 (0)編輯 收藏
            僅列出標(biāo)題
            共2頁: 1 2 
            97久久婷婷五月综合色d啪蜜芽 | 久久www免费人成看国产片| 久久国产成人精品麻豆| 国产精久久一区二区三区| 伊人久久大香线蕉AV一区二区| 亚洲精品美女久久777777| 大美女久久久久久j久久| 亚洲国产另类久久久精品黑人 | 久久精品国产亚洲av瑜伽| 久久夜色精品国产噜噜麻豆| 91亚洲国产成人久久精品| 亚洲中文字幕无码一久久区| 久久国产成人午夜aⅴ影院| 中文字幕无码精品亚洲资源网久久| 丰满少妇人妻久久久久久4| 久久不见久久见免费视频7| 亚洲欧美另类日本久久国产真实乱对白| 国产精品久久久久无码av| 青青草原精品99久久精品66| 伊人久久一区二区三区无码| 伊人久久综在合线亚洲2019 | 97久久久久人妻精品专区| 久久精品一本到99热免费| 免费精品久久久久久中文字幕| 国产精品激情综合久久| 久久久久综合网久久| 99久久婷婷国产综合亚洲| 久久精品国产亚洲av水果派| 思思久久99热只有频精品66| 亚洲精品成人网久久久久久| 亚洲第一永久AV网站久久精品男人的天堂AV | 久久人人青草97香蕉| 思思久久好好热精品国产| 色婷婷久久久SWAG精品| 精品久久久久久无码中文字幕| 久久综合九色综合精品| 国产成人精品久久一区二区三区| 久久精品无码午夜福利理论片 | 久久ZYZ资源站无码中文动漫 | 国产福利电影一区二区三区久久老子无码午夜伦不 | 久久久久国产一级毛片高清板|