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

兔子的技術博客

兔子

   :: 首頁 :: 聯系 :: 聚合  :: 管理
  202 Posts :: 0 Stories :: 43 Comments :: 0 Trackbacks

留言簿(10)

最新評論

閱讀排行榜

評論排行榜

      STL是C++標準庫的重要組成部分之一,它不僅是一個可復用的組件庫,更是一個包含算法與數據結構的軟件框架,同時也是C++泛型編程的很好例子。STL中運用了許多C++的高級技術。本文介紹函數對象,其實是接上一篇的話題,因為函數對象本質上還是重載操作符。主要參考了《C++ Primer》和《STL源碼剖析》。

      可以為類類型的對象重載函數調用操作符,定義了調用操作符的類,其對象稱之為函數對象(function object),即它們的行為類似函數對象。這是《C++ Primer》中的定義。下面通過一個例子來引出函數對象的使用。在我的解題筆記系列中,有一篇文章 解題筆記(16)——幾個數字的問題,其中第四個問題是調整數組順序使奇數位于偶數前面(數組)。輸入一個整數數組,調整數組中數字的順序,使得所有奇數位于數組的前半部分。所有偶數位于數組的后半部分。要求時間復雜度為O(n)。這個問題不難,其中用到了函數指針。代碼如下:

  1. bool IsOdd(int x)    
  2. {    
  3.     return (x & 1)? truefalse;    
  4. }    
  5. //函數功能 : 調整數組順序使奇數位于偶數前面    
  6. //函數參數 : pArray指向數組的指針,nLen為數組長度    
  7. //返回值 :   無    
  8. void PartionArray(int *pArray, int nLen, bool (*func)(int))    
  9. {    
  10.     int i = -1;    
  11.     for(int j = 0; j < nLen; j++)    
  12.     {    
  13.         if(func(pArray[j])) //滿足調整條件    
  14.         {    
  15.             i++;    
  16.             int tmp = pArray[j];    
  17.             pArray[j] = pArray[i];    
  18.             pArray[i] = tmp;    
  19.         }    
  20.     }    
  21. }   

      傳遞一個函數指針的好處是,可以很方便的修改調整的條件,這個問題希望將奇數放在前面,偶數放在后面。如果有另外一個問題,希望將正數放前面,負數放后面,那么只需定義新的調整函數,類似 IsOdd,然后將它作為參數傳遞給PartionArray函數即可。

      這里其實也可以使用函數對象,代碼如下:

  1. #include <iostream>  
  2. using namespace std;  
  3.   
  4. //函數對象  
  5. template<class T>  
  6. struct IsOdd  
  7. {  
  8.     bool operator() (T x){  
  9.         return (x & 1)?truefalse;  
  10.     }  
  11. };  
  12. //函數功能 : 調整數組順序使奇數位于偶數前面    
  13. //函數參數 : pArray指向數組的指針,nLen為數組長度    
  14. //返回值 :   無    
  15. template <class T, class F>  
  16. void PartionArray(T *pArray, int nLen, F func)  
  17. {    
  18.     int i = -1;    
  19.     for(int j = 0; j < nLen; j++)    
  20.     {    
  21.         if(func(pArray[j])) //滿足調整條件    
  22.         {    
  23.             i++;    
  24.             T tmp = pArray[j];    
  25.             pArray[j] = pArray[i];    
  26.             pArray[i] = tmp;    
  27.         }    
  28.     }    
  29. }    
  30. //測試用例  
  31. int main()  
  32. {  
  33.     short a[] = {1,2,3,4,5,6};  
  34.     long b[] = {1,2,3,4,5,6};  
  35.     PartionArray(a, 6, IsOdd<short>());   
  36.     PartionArray(b, 6, IsOdd<long>());   
  37.     return 0;  
  38. }  

       相比函數指針,函數對象的優勢在于能很好的滿足STL的抽象要求,同時更為靈活。上面這個例子算是一個引子,引出STL中函數對象的運用。

       STL中的函數對象并不是孤立的,而是與STL的算法緊密聯系在一起。舉個簡單的例子就明白了,比如我們希望利用STL的算法為一個數組排序,我們可以這樣做。

  1. #include <iostream>  
  2. #include <algorithm>  
  3. using namespace std;  
  4. int main()  
  5. {  
  6.     int a[] = {1,3,2,4,5,7};  
  7.     sort(&a[0], &a[6]);  
  8.     for(int i = 0; i < 6; i++)  
  9.         cout<<a[i]<<' ';  
  10.     cout<<endl;  
  11.     return 0;  
  12. }  
       這個排序算法默認是遞增排序,那么如果希望是遞減排序呢?很方便,在函數實參中加入一個函數對象即可。記住需包含頭文件 #include <functional>

  1. #include <iostream>  
  2. #include <functional>  
  3. #include <algorithm>  
  4. using namespace std;  
  5. int main()  
  6. {  
  7.     int a[] = {1,3,2,4,5,7};  
  8.     sort(&a[0], &a[6], greater<int>());  
  9.     for(int i = 0; i < 6; i++)  
  10.         cout<<a[i]<<' ';  
  11.     cout<<endl;  
  12.     return 0;  
  13. }  

         可以說在STL中,函數對象扮演著重要的角色,發揮著巨大的作用。下面列出了幾個常用的函數對象,摘自HP的STL源碼,做了部分修改。STL定義了兩個類,作為一元操作和二元操作的基類,這兩個基類僅僅是使用了內嵌型別技術,為什么要這樣子呢?后面介紹函數適配器時有說明,可以看到它的強大之處。

  1. //用來定義一元操作的參數類別和返回值類別  
  2. template <class Arg, class Result>  
  3. struct unary_function {  
  4.     typedef Arg argument_type;  //內嵌型別技術  
  5.     typedef Result result_type;  
  6. };  
  7. //用來定義二元操作的參數類別和返回值類別  
  8. template <class Arg1, class Arg2, class Result>  
  9. struct binary_function {  
  10.     typedef Arg1 first_argument_type;  
  11.     typedef Arg2 second_argument_type;  
  12.     typedef Result result_type;  
  13. };  
  14.   
  15. //一元操作,就兩個  
  16. template <class T>  
  17. struct negate : public unary_function<T, T> {  
  18.     T operator()(const T& x) const { return -x; }  
  19. };  
  20. template <class T>  
  21. struct logical_not : public unary_function<T,bool> {  
  22.     bool operator()(const T& x) const { return !x; }  
  23. };  
  24. //加減乘除取模  
  25. template <class T>  
  26. struct plus : public binary_function<T, T, T> {  
  27.     T operator()(const T& x, const T& y) const { return x + y; }  
  28. };  
  29. template <class T>  
  30. struct minus : public binary_function<T, T, T> {  
  31.     T operator()(const T& x, const T& y) const { return x - y; }  
  32. };  
  33. template <class T>  
  34. struct multiplies : public binary_function<T, T , T> {  
  35.     T operator()(const T& x, const T& y) const { return x * y; }  
  36. };  
  37. template <class T>  
  38. struct divides : public binary_function<T ,T, T> {  
  39.     T operator()(const T& x, const T& y) const { return x / y; }  
  40. };  
  41. template <class T>  
  42. struct modulus : public binary_function<T, T, T> {  
  43.     T operator()(const T& x, const T& y) const { return x % y; }  
  44. };  
  45. //關系運算  
  46. template <class T>  
  47. struct equal_to : public binary_function<T, T, bool> {  
  48.     bool operator()(const T& x, const T& y) const { return x == y; }  
  49. };  
  50. template <class T>  
  51. struct not_equal_to : public binary_function<T, T,bool> {  
  52.     bool operator()(const T& x, const T& y) const { return x != y; }  
  53. };  
  54. template <class T>  
  55. struct greater : public binary_function<T, T, bool> {  
  56.     bool operator()(const T& x, const T& y) const { return x > y; }  
  57. };  
  58. template <class T>  
  59. struct less : public binary_function<T, T, bool> {  
  60.     bool operator()(const T& x, const T& y) const { return x < y; }  
  61. };  
  62. template <class T>  
  63. struct greater_equal : public binary_function<T, T, bool> {  
  64.     bool operator()(const T& x, const T& y) const { return x >= y; }  
  65. };  
  66. template <class T>  
  67. struct less_equal : public binary_function<T, T, bool> {  
  68.     bool operator()(const T& x, const T& y) const { return x <= y; }  
  69. };  
  70. //邏輯運算  
  71. template <class T>  
  72. struct logical_and : public binary_function<T, T, bool>{  
  73.     bool operator()(const T& x, const T& y) const { return x && y; }  
  74. };  
  75. template <class T>  
  76. struct logical_or : public binary_function<T, T, bool>  
  77. {  
  78.   bool operator()(const T& x, const T& y) const { return x || y; }  
  79. };  

      上面這些函數對象都比較簡單,接下來介紹幾個稍微復雜點的,它們被稱為函數適配器(function adapter),用于特化和擴展一元和二元函數對象。分為兩類,第一是綁定器(binder),它通過將一個操作數綁定到給定值而將二元函數對象轉換為一元函數。第二是求反器(negator),它將謂詞函數對象的真值求反。這些定義來自《C++ Primer》一書。書上還給了兩個例子,這里羅列一下:

  1. #include <iostream>  
  2. #include <functional>  
  3. #include <vector>  
  4. #include <algorithm>  
  5. using namespace std;  
  6. int main()  
  7. {  
  8.     vector<int> vec(10, 1);  
  9.     int count1 = count_if(vec.begin(), vec.end(), bind2nd(less_equal<int>(), 10));       //求容器中小于等于10的元素個數  
  10.     int count2 = count_if(vec.begin(), vec.end(), not1(bind2nd(less_equal<int>(), 10))); //求容器中不小于等于10的元素個數,正好是上面結果的取反  
  11.     cout<<count1<<' '<<count2<<endl;  //10 0  
  12.     return 0;  
  13. }  
        下面分析一下STL是如何實現函數適配器的,先給出STL的源碼。已經整理過了。

  1. //綁定第一個參數  
  2. template <class Operation>   
  3. class binder1st: public unary_function<typename Operation::second_argument_type, typename Operation::result_type> {  
  4. public:  
  5.     binder1st(const Operation& x, const typename Operation::first_argument_type& y) : op(x), value(y) {} //構造函數  
  6.     typename Operation::result_type operator()(const typename Operation::second_argument_type& x) const {  
  7.         return op(value, x);  //固定第一個參數  
  8.     }  
  9. protected:  
  10.     Operation op;  
  11.     typename Operation::first_argument_type value;  
  12. };  
  13. //綁定第二個參數  
  14. template <class Operation>   
  15. class binder2nd: public unary_function<typename Operation::first_argument_type,typename Operation::result_type> {  
  16. public:  
  17.     binder2nd(const Operation& x, const typename Operation::second_argument_type& y) : op(x), value(y) {}  
  18.     typename Operation::result_type operator()(const typename Operation::first_argument_type& x) const {  
  19.         return op(x, value);  //固定第二個參數  
  20.     }  
  21. protected:  
  22.     Operation op;  
  23.     typename Operation::second_argument_type value;  
  24. };  
  25. //外部接口  
  26. template <class Operation, class T>  
  27. inline binder1st<Operation> bind1st(const Operation& fn, const T& x) {  
  28.     typedef typename Operation::first_argument_type Arg1_type;  
  29.     return binder1st<Operation>(fn,Arg1_type(x));  
  30. }  
  31. //外部接口  
  32. template <class Operation, class T>  
  33. inline binder2nd<Operation> bind2nd(const Operation& fn, const T& x) {  
  34.     typedef typename Operation::second_argument_type Arg2_type;  
  35.     return binder2nd<Operation>(fn, Arg2_type(x));  
  36. }  
  1. //一元操作求反  
  2. template <class Predicate>  
  3. class unary_negate: public unary_function<typename Predicate::argument_type, bool> {  
  4. protected:  
  5.     Predicate pred;  
  6. public:  
  7.     explicit unary_negate(const Predicate& x) : pred(x) {}  
  8.     bool operator()(const typename Predicate::argument_type& x) const {  
  9.     return !pred(x);  
  10.   }  
  11. };  
  12. //二元操作求反  
  13. template <class Predicate>   
  14. class binary_negate : public binary_function<typename Predicate::first_argument_type, typename Predicate::second_argument_type,bool> {  
  15. protected:  
  16.     Predicate pred;  
  17. public:  
  18.     explicit binary_negate(const Predicate& x) : pred(x) {}  
  19.     bool operator()(const typename Predicate::first_argument_type& x, const typename Predicate::second_argument_type& y) const {  
  20.         return !pred(x, y);   
  21.     }  
  22. };  
  23. //外部接口  
  24. template <class Predicate>  
  25. inline unary_negate<Predicate> not1(const Predicate& pred)  
  26. {  
  27.     return unary_negate<Predicate>(pred);  
  28. }  
  29. //外部接口  
  30. template <class Predicate>  
  31. inline binary_negate<Predicate> not2(const Predicate& pred)  
  32. {  
  33.     return binary_negate<Predicate>(pred);  
  34. }  
          到這里,我們可以回答之前的一個問題,就是STL為什么要定義兩個基類,里面僅僅是內嵌型別。通過上面代碼,不難發現,原來是用來萃取函數對象所操作的數據類型。比如 binder1st 這個類,它的模板中只有一個形參,它繼承自unary_function,而unary_function的模板有兩個形參。如何實現這種繼承關系呢?內嵌型別技術,因為binder1st 的模板實參是個函數對象,繼承自unary_function或binary_function,通過內嵌型別技術很容易萃取出數據類型。

         再進一步,函數適配器是如何工作的呢?

  1. include <iostream>  
  2. #include <functional>  
  3. #include <vector>  
  4. #include <algorithm>  
  5. using namespace std;  
  6. int main()  
  7. {  
  8.     vector<int> vec(10, 1);  
  9.     int count1 = count_if(vec.begin(), vec.end(), bind2nd(less_equal<int>(), 10));       //求容器中小于等于10的元素個數  
  10.     int count2 = count_if(vec.begin(), vec.end(), not1(bind2nd(less_equal<int>(), 10))); //求容器中不小于等于10的元素個數,正好是上面函數的取反  
  11.     cout<<count1<<' '<<count2<<endl;  //10 0  
  12.     return 0;  
  13. }  
        還是以這個程序為例,介紹一下count_if(vec.begin(), vec.end(), bind2nd(less_equal<int>(), 10))具體執行。首先執行bind2nd(less_equal<int>(), 10)這個函數,這個函數會返回一個binder2nd的函數對象,注意構造這個函數對象的時候,binder2nd(const Operation& x, const typename Operation::second_argument_type& y) : op(x), value(y) {} 。第二個參數value的值設置為10,而第一個參數op設置成less_equal<int>()這個函數對象。

       接著count_if 執行時,下面是它的源碼。執行時,pred(*first)其實就是binder2nd中的運算,而這個運算的第二個參數是固定的,也就是10,所以pred只傳遞了一個實參進去就可以了。

  1. template <class InputIter, class Predicate, class Size>  
  2. void count_if(InputIter first, InputIter last, Predicate pred, Size& n) {  
  3.     for ( ; first != last; ++first)  
  4.         if (pred(*first))  
  5.             ++n;  
  6. }  
  7. template <class InputIter, class Predicate>  
  8. typename iterator_traits<InputIter>::difference_type count_if(InputIter first, InputIter last, Predicate pred) {  
  9.     typename iterator_traits<InputIter>::difference_type n = 0;  
  10.     for ( ; first != last; ++first)  
  11.         if (pred(*first))  
  12.             ++n;  
  13.     return n;  
  14. }  
        下面把上述綜合起來,通過修改STL,寫個完整的測試程序。如下所示,注意這里用的都是自定義的代碼,沒有包含STL的函數對象和函數。

  1. #include <iostream>  
  2. #include <vector>  
  3. using namespace std;  
  4.   
  5. //count_if函數  
  6. template <class InputIter, class Predicate, class Size>  
  7. void count_if(InputIter first, InputIter last, Predicate pred, Size& n) {  
  8.     for ( ; first != last; ++first)  
  9.         if (pred(*first))  
  10.             ++n;  
  11. }  
  12. //用來定義一元操作的參數類別和返回值類別  
  13. template <class Arg, class Result>  
  14. struct unary_function {  
  15.     typedef Arg argument_type;  
  16.     typedef Result result_type;  
  17. };  
  18. //用來定義二元操作的參數類別和返回值類別  
  19. template <class Arg1, class Arg2, class Result>  
  20. struct binary_function {  
  21.     typedef Arg1 first_argument_type;  
  22.     typedef Arg2 second_argument_type;  
  23.     typedef Result result_type;  
  24. };  
  25. //本測試之用到關系函數對象  
  26. template <class T>  
  27. struct less_equal : public binary_function<T, T, bool> {  
  28.     bool operator()(const T& x, const T& y) const { return x <= y; }  
  29. };  
  30. //綁定第二個參數  
  31. template <class Operation>   
  32. class binder2nd: public unary_function<typename Operation::first_argument_type,typename Operation::result_type> {  
  33. public:  
  34.     binder2nd(const Operation& x, const typename Operation::second_argument_type& y) : op(x), value(y) { cout<<"binder2nd Constructor"<<endl; }  
  35.     typename Operation::result_type operator()(const typename Operation::first_argument_type& x) const {  
  36.         cout<<"binder2nd's operator()"<<endl;  
  37.         return op(x, value);  //固定第二個參數  
  38.     }  
  39. protected:  
  40.     Operation op;  
  41.     typename Operation::second_argument_type value;  
  42. };  
  43. //外部接口  
  44. template <class Operation, class T>  
  45. inline binder2nd<Operation> bind2nd(const Operation& fn, const T& x) {  
  46.     typedef typename Operation::second_argument_type Arg2_type;  
  47.     return binder2nd<Operation>(fn, Arg2_type(x));  
  48. }  
  49. //一元操作求反  
  50. template <class Predicate>  
  51. class unary_negate: public unary_function<typename Predicate::argument_type, bool> {  
  52. protected:  
  53.     Predicate pred;  
  54. public:  
  55.     explicit unary_negate(const Predicate& x) : pred(x) { cout<<"unary_negate Constructor"<<endl; }  
  56.     bool operator()(const typename Predicate::argument_type& x) const {  
  57.     cout<<"unary_negate's operator()"<<endl;  
  58.     return !pred(x);  
  59.   }  
  60. };  
  61. //外部接口  
  62. template <class Predicate>  
  63. inline unary_negate<Predicate> not1(const Predicate& pred)  
  64. {  
  65.     return unary_negate<Predicate>(pred);  
  66. }  
  67. //測試程序  
  68. int main()  
  69. {  
  70.     vector<int> vec(10, 1);  
  71.     int count1 = 0, count2 = 0;  
  72.     count_if(vec.begin(), vec.end(), bind2nd(less_equal<int>(), 10),count1);       //求容器中小于等于10的元素個數  
  73.     count_if(vec.begin(), vec.end(), not1(bind2nd(less_equal<int>(), 10)),count2); //求容器中不小于等于10的元素個數,正好是上面函數的取反  
  74.     cout<<count1<<' '<<count2<<endl;  //10 0  
  75.     return 0;  
  76. }  
出處 http://blog.csdn.net/wuzhekai1985
原文:http://blog.csdn.net/wuzhekai1985/article/details/6658940
posted on 2011-09-06 10:42 會飛的兔子 閱讀(1385) 評論(0)  編輯 收藏 引用 所屬分類: C++庫,組件
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            久久久久9999亚洲精品| 久久综合久久综合九色| 免费观看30秒视频久久| 久久xxxx精品视频| 欧美在线免费视频| 久久久国产精品一区二区三区| 亚洲特色特黄| 中日韩男男gay无套| 亚洲香蕉网站| 欧美在线视频一区二区三区| 欧美在线观看网址综合| 老司机午夜精品视频在线观看| 欧美成人免费观看| 99国产精品视频免费观看一公开 | 欧美成人激情视频| 91久久国产综合久久蜜月精品| 久久婷婷综合激情| 亚洲日本aⅴ片在线观看香蕉| 亚洲美女在线视频| 久久爱www久久做| 欧美精品在线看| 国产日韩欧美不卡| 亚洲精品国产视频| 久久精品国产欧美激情| 最新高清无码专区| 欧美一区二区三区四区在线观看| 欧美大片va欧美在线播放| 国产精品视频yy9299一区| 亚洲国产精品欧美一二99| 亚洲深夜激情| 欧美国产大片| 久久超碰97人人做人人爱| 欧美日韩另类视频| 亚洲欧洲在线视频| 久久久人成影片一区二区三区观看 | 欧美激情一二三区| 亚洲免费网站| 欧美日韩在线视频一区| 国产亚洲欧美一区在线观看| 夜夜嗨av色综合久久久综合网 | 日韩亚洲在线| 模特精品裸拍一区| 激情综合视频| 久久久久久久久久码影片| 亚洲深夜影院| 国产精品ⅴa在线观看h| 亚洲精品乱码久久久久| 葵司免费一区二区三区四区五区| 亚洲性视频网站| 欧美午夜不卡影院在线观看完整版免费| 精品不卡一区| 免费成人性网站| 久久久五月天| 精品88久久久久88久久久| 欧美一区二区三区四区在线观看| 亚洲免费高清| 久久野战av| 91久久中文字幕| 农村妇女精品| 亚洲精品日韩在线观看| 亚洲第一福利社区| 欧美国产先锋| 在线视频欧美日韩精品| 亚洲欧洲在线视频| 欧美激情精品久久久六区热门| 亚洲狠狠婷婷| 亚洲激情自拍| 欧美日韩一区二区三区视频 | 国产综合av| 久久久亚洲影院你懂的| 久久久久久久欧美精品| 亚洲电影av在线| 91久久精品国产91性色tv| 欧美精品手机在线| 亚洲欧美韩国| 欧美影院视频| 亚洲国产福利在线| 日韩网站在线| 国产日韩欧美高清免费| 老巨人导航500精品| 男人的天堂亚洲| 亚洲一区欧美激情| 久久精品72免费观看| 亚洲精品小视频| 亚洲一级片在线看| 一区在线电影| 99国产精品99久久久久久粉嫩| 国产精品久久久久一区二区| 欧美在线观看天堂一区二区三区| 久久久美女艺术照精彩视频福利播放| 亚洲国产欧美在线人成| 一区电影在线观看| 在线欧美亚洲| 一本到12不卡视频在线dvd| 国产色婷婷国产综合在线理论片a| 欧美成人日韩| 国产精品视频免费观看| 毛片基地黄久久久久久天堂| 欧美精品久久一区| 久久精品人人做人人综合| 欧美激情视频一区二区三区免费| 亚洲制服av| 狂野欧美激情性xxxx欧美| 一区二区三区四区国产| 久久久美女艺术照精彩视频福利播放| 中文网丁香综合网| 久久蜜桃av一区精品变态类天堂| 亚洲视频网站在线观看| 久久综合久久综合久久| 欧美一区二区三区婷婷月色| 欧美精品一区在线| 欧美a级一区二区| 国产农村妇女毛片精品久久莱园子| 亚洲国产精品成人综合| 精品成人一区| 欧美一级淫片aaaaaaa视频| 亚洲视频999| 欧美va天堂在线| 国产精品二区二区三区| 亚洲成人在线视频网站| 午夜电影亚洲| 亚洲天堂免费观看| 欧美精品电影| 亚洲福利专区| 亚洲第一视频网站| 久久精品国产亚洲aⅴ| 欧美一区免费视频| 国产精品久久久久久久久久免费看| 亚洲国内高清视频| 亚洲第一精品电影| 久久女同互慰一区二区三区| 久久精品亚洲乱码伦伦中文| 国产精品久久久久久影视| 99精品热视频| 亚洲一区久久久| 国产精品高清在线| 亚洲一区日韩在线| 欧美在线观看视频| 激情av一区| 毛片一区二区三区| 亚洲大胆人体视频| 亚洲精品网址在线观看| 欧美黄色精品| 一区二区三区国产精华| 亚洲欧美日韩精品久久久| 国产精品女人毛片| 欧美一区二区精品在线| 六月天综合网| 亚洲精品一区二区三区婷婷月| 欧美国产视频在线观看| 日韩网站在线观看| 欧美中文在线观看国产| 黄色成人在线观看| 欧美国产国产综合| 中文国产成人精品久久一| 欧美一级成年大片在线观看| 国产精品一区一区| 久久久久88色偷偷免费| 亚洲国产合集| 亚洲综合精品自拍| 国产综合婷婷| 欧美岛国在线观看| 亚洲香蕉成视频在线观看| 久久精品亚洲一区二区| 一区二区在线视频| 欧美日韩在线视频一区| 欧美在线免费视频| 亚洲人成在线播放| 久久久www| aⅴ色国产欧美| 国产亚洲欧美一区在线观看| 女女同性女同一区二区三区91| 一区二区三区视频在线播放| 久久久夜色精品亚洲| 亚洲最黄网站| 一区二区三区在线视频免费观看| 欧美国产日韩一区| 久久精品日韩欧美| 亚洲午夜91| 亚洲高清在线视频| 久久精品一区中文字幕| 夜夜嗨av一区二区三区| 揄拍成人国产精品视频| 欧美三级韩国三级日本三斤| 久久精品网址| 亚洲一区二区在线看| 亚洲国产视频一区| 六月婷婷久久| 久久精品国产清高在天天线 | 国产精品一区二区a| 欧美激情精品久久久久久蜜臀| 亚洲欧美激情四射在线日 | 欧美三级韩国三级日本三斤| 久久激情视频免费观看| 亚洲午夜女主播在线直播| 亚洲经典在线看| 嫩草影视亚洲| 久久久免费精品| 性做久久久久久久久| 亚洲网址在线|