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

OnTheWay2012
埋葬昨天的我,迎來重生的我!
posts - 15,  comments - 89,  trackbacks - 0
        很久以前就對基于引用計數的指針指針很感興趣,今天突然又一次想到這個問題,所以就寫了一個基于引用技術的智能指針。該智能指針的具體實現方式如下:
  1#include <iostream>
  2#include <numeric>
  3#include <algorithm>
  4#include <map>
  5#include <assert.h>
  6
  8
  9using namespace std;
 10
 11template<typename T>
 12class SmartPointByRefCount
 13{
 14public:
 15    SmartPointByRefCount(T* pT) : m_pT(pT)
 16    {
 17        SmartPointByRefCount::AddRefCount((unsigned int)m_pT);
 18    }

 19
 20    SmartPointByRefCount(const SmartPointByRefCount& ref)
 21    {
 22        SmartPointByRefCount::AddRefCount((unsigned int)(ref.m_pT));
 23        m_pT = ref.m_pT;
 24    }

 25
 26    SmartPointByRefCount& operator=(const SmartPointByRefCount& ref)
 27    {
 28        if (this != &ref)
 29        {
 30            SmartPointByRefCount::AddRefCount(ref.m_pT);
 31            m_pT = ref.m_pT;
 32        }

 33
 34        return *this;
 35    }

 36
 37    ~SmartPointByRefCount()
 38    {
 39        if (SmartPointByRefCount::IsShouldDelete((unsigned int)m_pT))
 40        {
 41            SmartPointByRefCount::DelRefCount((unsigned int)m_pT);
 42            delete m_pT;
 43        }

 44        else
 45        {
 46            SmartPointByRefCount::RedRefCount((unsigned int)m_pT);
 47        }

 48    }

 49
 50    T* operator->()
 51    {
 52        return m_pT;
 53    }

 54
 55    T& operator*()
 56    {
 57        return *m_pT;
 58    }

 59
 60private:
 61    T *m_pT;
 62
 63private:
 64    static std::map<unsigned int, unsigned int> m_mapUseCount;
 65
 66public:
 67    static bool IsShouldDelete(unsigned int);
 68    static void AddRefCount(unsigned int);
 69    static void RedRefCount(unsigned int);
 70    static void DelRefCount(unsigned int);
 71}
;
 72
 73
 74template<typename T>  std::map<unsigned int, unsigned int> SmartPointByRefCount<T>::m_mapUseCount;
 75
 76template<typename T>  
 77bool SmartPointByRefCount<T>::IsShouldDelete(unsigned int nPointer)
 78{
 79    std::map<unsigned int, unsigned int>::const_iterator it = m_mapUseCount.find(nPointer);
 80    if (it != m_mapUseCount.end())
 81    {
 82        return ( 1 == it->second );
 83    }

 84    else
 85    {
 86        assert(false);
 87        return false;
 88    }

 89}

 90
 91template<typename T>  
 92void SmartPointByRefCount<T>::AddRefCount(unsigned int nPointer)
 93{
 94    std::map<unsigned int, unsigned int>::iterator it = m_mapUseCount.find(nPointer);
 95    if (it != m_mapUseCount.end())
 96    {
 97        (it->second)++;
 98    }

 99    else
100    {
101        m_mapUseCount[nPointer] = 1;
102    }

103}

104
105template<typename T>  
106void SmartPointByRefCount<T>::RedRefCount(unsigned int nPointer)
107{
108    std::map<unsigned int, unsigned int>::iterator it = m_mapUseCount.find(nPointer);
109    if (it != m_mapUseCount.end() && 1 < it->second)
110    {
111        (it->second)--;
112    }

113    else
114    {
115        assert(false);
116    }

117}

118
119template<typename T>  
120void SmartPointByRefCount<T>::DelRefCount(unsigned int nPointer)
121{
122    std::map<unsigned int, unsigned int>::iterator it = m_mapUseCount.find(nPointer);
123    if (it != m_mapUseCount.end())
124    {
125        m_mapUseCount.erase(it);
126    }

127    else
128    {
129        assert(false);
130    }

131}
        以下是測試代碼,該智能指針能夠完全通過這些測試代碼。
 1SmartPointByRefCount<int> TestSPR(SmartPointByRefCount<int> dd)
 2{
 3    *dd = 4;
 4    return dd;
 5}

 6
 7
 8int main(int argc, char *argv)
 9{
10    SmartPointByRefCount<int> spb1(new int(0));
11    SmartPointByRefCount<int> spb2 = TestSPR(spb1);
12    *spb1 = 2;
13
14    
15    {
16        SmartPointByRefCount<int> spb3(spb2);
17        SmartPointByRefCount<int> spb4 = TestSPR(spb3);
18    }

19
20    return 0;
21}

        寫完這個智能指針之后我在網上找了找其他人寫的智能指針,發現智能指針有兩種典型實現方式:侵入式、非侵入式,而我的實現方式是非侵入式的。以下兩篇文章是從網上引用的,從這兩篇文章中發現了一些問題,也學到了一些知識。以下引用內容的所有版權歸原作者所有。

第一篇:
             一種自適應的引用計數智能指針的實現

0 引言
        自行管理內存是C ++ 語言的一個重要特征, 它為開發人員充分、靈活利用內存空間提供了方 便,但同時也負擔了大量內存的請求、釋放工作.
 程序的邏輯錯誤以及不確定的異常引發,通常會由于內存未釋放而造成系統的內存泄漏. 實際工 作證明,內存泄漏是最主要的C + + 程序Bug 之 一,由程序進行自動內存管理可有效地避免內存 泄漏,這也是提高C + + 程序質量的重要途經之 一.
自動內存管理通常的方式是引入垃圾回收 (Garbage Collection) 機制. 垃圾回收作為動態語言 的特征之一早已存在于多種程序設計語言中,如 Java、Python 等. 遺憾的是最新的C ++ 標準并沒有將其引入,同時,由于C ++ 語言是強類型的靜態語言,通過程序來模擬垃圾回收機制非常困難,且功能有限. 避開垃圾回收,通過運用C ++ 語言的運算符重載和范型機制,在C ++ 社區產生了稱為智能指針(Smart Pointer) 的內存工具. 所謂智能指針,實際上是一種類模板,當其實例化后包含有指向動態分配內存的指針,它通過重載* 、->運算符來模擬指針的行為,同時在適當的時候釋放內存,以達到自動內存管理的目的,其定義通常為template < typename T > class Smart Ptr. 現在,智能指針在C ++ 應用開發中大量使用, 已經成為C ++ 標準的工具之一.

1   智能指針的一般實現和使用
 通常,智能指針按使用的策略分為兩類:一類是面向控制資源的所有權的智能指針,這類智能指針保證資源只被一個確定的對象使用,任何智能指針的拷貝或傳遞均會發生所有權的轉換,如標準庫提供的std : :auto ptr[1 ] ;另一類是面向資源共享的智能指針,這類智能指針內部通常存在使用資源的記數器,稱為引用計數,它保證引用計數為0 時(即不再有對象使用資源) 釋放資源, 如Boost 庫的boost : :shared ptr[2 ] . 智能指針能很好的完成內存自動釋放,而它
 的使用與普通指針非常類似:
 {
    ??
    //定義int 的智能指針si
       boost : :shared ptr < int > si = new int (1) ;
      //直接使用si
      std::cout<<*si<<std : :endl ;
      //定義string 的智能指針st
      boost::shared-ptr<std::string > st = new std::string(″Foo″) ;
      //通過- > 運算符訪問string 的成員函數
      st->clear () ;
      //qt 和st 訪問的是同一資源
      boost : :shared ptr < std : :string > qt = st ;
      qt - > append(″Bar″) ;
       ??
       //si st 中的指針將自動釋放
 }

 2   引用計數的實現
        資源共享型的智能指針引用計數的設計,一般分侵入式與非侵入式兩種. 侵入式引用計數,將計數器作為包含對象的一部分,該方法效率比較 高,但要求包含類型總是繼承自一個計數對象;非侵入式引用計數,計數器通過動態內存分配獲得,任何的對象均可作為智能指針的范型參數,但小內存的new 操作會降低智能指針的效率. 關于效率和靈活的平衡,在智能指針的設計中是不能完成的,只有把這個問題交給智能指針的使用者. 但通過模板元編程以及模板偏特化,我們可以為使用者提供自動識別包含類型的智能指針[3 ] . 通過模板元編程可在程序的編譯期間判斷一個類型是否繼承自計數對象,如果是則采用侵入式,否則采用非侵入式.侵入式的引用計數應繼承的基類:
   class IntrusiveRefCount
   {
   //操作引用計數成員函數
   ??
   protected :
     int refCount ;PPP< 引用計數
  } ;
  通過不同的方式實現智能指針,模板參數IntrRefCount 缺省為True ,即采用侵入式:
  template < typename T,bool IntrRefCount >
  class SmartPtrImp
  {
    //重載賦值運算符.
     //通過調用T的成員函數DecRef()和IncRef ( ) 來改變引用值
        SmartPtrImp &operator = (const SmartPtrImp &sptr)
        {
          //釋放當前資源
          if (pointee ! = 0 &&pointee - > DecRef ( ) == 0)
             delete pointee ;
          pointee = sptr.pointee ;
          if (pointee ! = 0)
            pointee->IncRef() ;
          return *this ;
         }
         //拷貝構造函數. 同樣有引用值的操作
         SmartPtrImp (const SmartPtrImp &sptr) ;
 protected :
             T *pointee ;///對象指針
    };
   采用模板偏特化參數IntrRefCount ( 特化為false) ,此類模板采用非侵入式模式:
   template < typename T>
   class SmartPtrImp < T,false >
   {
     //重載賦值運算符.
   //直接new int (0) 來獲取記數器
           SmartPtrImp &operator = (T* ptr)
          {
                   if (pointee ! = 0)
                   {
                             if (--(*refCountPtr ) == 0)
                                    delete pointee ;
                           else
                           //失去了對原對象的控制,原對象的引用計數也要放棄
                               refCountPtr = new int (0) ;
                     }
                  pointee = ptr ;
                  if (pointee ! = 0)
                          ++refCountPtr ;
          return *this ;
 }
         //拷貝構造函數. 同樣有引用值的操作
         SmartPtrImp (const SmartPtrImp &sptr) ;
  protected :
         T *pointee ;///對象指針
        int *refCountPtr;///引用計數
 } ;
 
3        智能指針的實現
        現在我們需要一個算法判斷一個類是否是另一個類的子類的范型算法[4 ] ,實現如下:
        //如果沒有看過陳偉柱翻譯的《C++ Template》的話下面的代碼可能很難看懂,如果看不懂的話,不妨找這本書看一下
         template < typename D ,typename B >
         struct IsDerivedFrom
         {
                 class No {} ;
                 class Yes {No no[2 ] ;} ;
              static Yes Test (B*) ;
           static No Test ( ?) ;
              enum {Is = sizeof (Test ( static cast <D*> (0) ) ) = = sizeof(Yes) } ;
         } ;
         如果類型D 是B 的子類IsDerivedFrom < D ,B>::Is 的值就為1.
         有了如上工具,我們就可以將智能指針的實現拼接起來:
           template < typename T>
           class SmartPtr :
        public SmartPtrImp < T, IsDerivedFrom < T, IntrusiveRefCount>::Is == 1 >
           {
          typedef SmartPtrImp < T, IsDerivedFrom < T, IntrusiveRefCount>::Is == 1, Deletor < T > > ParentCls ;
        public :
         SmartPtr () :ParentCls () {}
      explicit SmartPtr (T &t) :ParentCls (t) {}
          explicit SmartPtr (T*t) :ParentCls (t) {}
       SmartPtr (const SmartPtr &sptr) :ParentCls (sptr) {}
     }

                          
        從以上的說明上看,這篇論文只有一點有價值的——講明白了智能指針的兩種實現方式,侵入式和非侵入式。至于這篇自適應的說法,個人感覺在編碼的時候根本不會用到。其中紅色的文字是我添加的。


第二篇:

        指針 是C++中不得不談的一個話題,或許我還不是很能熟練的掌握指針以及我所要討論的引用計數型指針的全部,但是還是有那么些迫不及待想要表達一下。
        指針pointer 是 資源泄漏 resource leak 的根源(當然可能還有其他一些什么東西,在我的映像中 異常 仿佛也會造成資源泄漏)最簡單的一個資源泄漏的例子就是new和delete這樣的動態內存分配算子沒有正確使用造成的:
struct A
{
A()  { printf("A Constructor!"); }
~A() { printf("A Destructor!"); }
};

void area()
{
A *p = new A();
}
執行完 area() 后,自然是只有A構造的消息,而A的析構卻不見影蹤。這里我們在離開了area作用域后,我們就無法對p所指向之資源進行操作,A的實例就會被懸掛在內存的某處得不到清理。一個形象點的比方就像人類發送的宇宙衛星失去了動力以及和地球的聯系,無法收回,就變成了宇宙垃圾~。
然而利用對象來管理資源是一個很好的辦法,因為對象的實例本身在脫離作用域后會自動清理,就像這樣

class  A_holder
{
public:
expilict A_holder(A* p = NULL):ptr(p) {}

~A_holder()
{
if (ptr)
delete ptr;
}
private:
A* ptr;
};
如此,我們在area里面把資源的管理權力交給A_holder,就像下面這樣
void area()
{
A_holder ah(new A);
}
這樣,ah在離開area后會自動調用其析構函數,就達到了自動管理該資源的目的。
利用C++的類的實例離開作用域會自動調用其析構函數的機制,可以比較方便的管理資源,但是在使用普通指針的情況下會存在多個指針指向同一對象的情況。
void multi_point()
{
int a;
int *p1,*p2;

p1 = &a;
p2 = &a;
}
實際的指針指向情況應該是這樣 p1 –>? a ?<- p2。
這里就出現了一個問題,我們想取消p1的時候可能會出現兩種語義:
1、將p1和其指向的對象一起刪除,這樣p2也就不可以繼續對a進行使用。但是往往p2的使用者不會知道a已經刪除,則出現了錯誤。
2、將p1與其指向的對象解除關系,這樣p2還可以對a進行使用。
對于普通的delete操作,實現的是第一種情況,這樣通過p2對a進行訪問必然會造成致命的錯誤。
在實現holder類的時候應該也考慮到第二種情況,如果有另外一個holder也指向這個資源,其中一個holder銷毀,另外一個holder還可能會使用到它們共同指向的那個資源。于是,holder的作用就不僅僅是單單的持有和施放資源,還應該處理有多少個對其hold資源的引用(即引用計數),并且在引用計數降為0時真正的銷毀資源實體。
如此,一個行為類似指針(有->,*操作符)的智能指針出現,它管理賦予其資源的引用計數,也管理該資源的生死存亡。
一個簡單的Reference Count Smart Pointer的實現如下:
#ifndef COUNTED_PTR_HPP
#define COUNTED_PTR_HPP
/*class for counted reference semantics
*-deletes the object to which it refers when the last CountedPtr
* that refers to it is destroyed
*/
template <class T>
class CountedPtr
{
private:
 T* ptr;        // pointer to the value
 long* count;   // shared number of owners
public:
 //initialize pointer with existing pointer
 //-requires that the pointer p is a return value of new
 explicit CountedPtr (T* p=0)
  : ptr(p), count(new long(1)) {}
 //copy pointer (one more owner)
 CountedPtr (const CountedPtr<T>& p) throw()
  : ptr(p.ptr), count(p.count)
 {
  ++*count;
 }
 //destructor (delete value if this was the last owner)
 ~CountedPtr () throw()
 {
  dispose();
 }
 //assignment (unshare old and share new value)
 CountedPtr<T>& operator= (const CountedPtr<T>& p) throw() {
  if (this != &p) {
   dispose();
   ptr = p.ptr;
   count = p.count;
   ++*count;
  }
  return *this;
 }
 //access the value to which the pointer refers
 T& operator*() const throw() {
  return *ptr;
 }
 T* operator->() const throw() {
  return ptr;
 }
private:
 void dispose() {
  if (--*count == 0) {
   delete count;
   delete ptr;
  }
 }
};
#endif /*COUNTED_PTR_HPP*/
由此,一個新的問題出現了!循環引用!
這樣的一個引用計數型智能指針目的是為了防止資源泄漏,但是只需要一個很小巧的代碼就可以讓這樣的初衷化為烏有……。
class A
{
public:
 A() {cout<<"A CON"<<endl;}
 ~A() {cout<<"A DES"<<endl;}

 void hold(CountedPtr<A> ptr)
 {
  m_ptr = ptr;
 }
private:
 CountedPtr<A> m_ptr;
};

void self_cir_area()
{
 CountedPtr<A> pA(new A());
 pA->hold(pA);
}

可以看見,一個對象A中有一個引用計數型智能指針,這樣的設計可能會很常見(指向自身類型的結構體——鏈表)
但是,當自身循環引用發生的時候會怎么樣呢? 下面就來看看這么兩句代碼
CountedPtr<A> pA(new A());
這里我們新建一個資源,并且把這個資源的管理權移交給pA這個引用計數型智能指針對象管理。如此,pA中的引用計數被初始化為1。
pA->hold(pA);
這里,我們把pA對象傳入給實例化的A對象中的引用計數型智能指針m_ptr,m_ptr執行這樣的一個成員函數:   
//assignment (unshare old and share new value)
CountedPtr<T>& operator= (const CountedPtr<T>& p) throw() {
 if (this != &p) {
  dispose();
  ptr = p.ptr;
  count = p.count;
  ++*count;
 }
 return *this;
}
因為這里很明顯不是自身賦值,A中的m_ptr和pA不是同一個對象,所以進入if結構中調用下面的內容。dispose是用作清理,因為m_ptr并沒有指向任何東西,所以第一個函數并沒有真正的意義。然后
m_ptr.ptr = pA.ptr;
m_ptr.count = pA.count;
++(*m_ptr.count);  //(*pA.count)也被++
到此,pA的引用計數為2
嗯,下面就pA這個對象理所當然的離開了作用域,調用其析構函數:
~CountedPtr () throw() {
 dispose();
}
噢,是一個轉向,調用其private成員函數dispose():
void dispose() {
 if (--*count == 0) {
  delete count;
  delete ptr;
 }
}
很簡單,將引用計數-1,由2變成1,不為0,所以if結構內的語句不被執行。
由此,我們又制造了一個完美的太空垃圾……
這樣的循環引用問題應該是在設計的過程中就應該避免的,如果用UML語言描述
A中持有一個 引用計數型智能指針 的語義就是 這個 持有關系 是需要在 A消失的時候所持有的對象也隨之消失(這正是智能指針的作用,在脫離作用域自動清除其持有的資源)。如此就構成了 組合 關系。如果要表示 聚合 關系,即有 部分-整體 關系但是部分不隨整體的消失而消失,這就不是 智能指針 所表達的語義。
還有可能遇見的循環引用就是 A1 持有 A2, A2 持有 A1 的情況……
這樣A1,A2中對雙方的引用計數都是2,當一方“銷毀”的時候,雙方的應用計數都變為1,實際上并沒有銷毀任何東西,制造了兩個完美無暇的太空垃圾~
這里又引發出一個問題,這樣的資源泄漏問題實際上還是由程序員自身引起的。
C++之所以是一個很容易出錯的語言,很大一部分在于其資源的管理權力全權交給了程序員。這樣的權力到底是造福了程序員還是迷惑了程序員呢?
這里我卻想起了蜘蛛俠中的一句名言: “一個人能力有多大,責任就有多大!”
對C++中指針的指責不是一天兩天了,其易錯性無可厚非,但是它卻給了你其他語言無法給你的能力!這就是我的觀點,你能力有這么大,你就有責任來治理好這些資源。而非一再推卸責任。如果真的是要推卸責任,也就應該去選擇其他那些剝奪你的能力而減少你的責任的語言,因為你有選擇權!就像說英語和中文一樣,并沒有哪個人在強迫你,不是么?熱愛C++是一種態度,對一個語言的利弊都了然于心,了解其可以做什么不可以做什么,怎樣才可以更好的使用它來做什么,才能更好的使用它。更何況,there are rarely things that are not possible in C++。

 

在沒有看到這篇文章之前,我覺得智能指針能夠應對所有情況,可是看過這篇文章讓我了解到智能指針在循環引用的情況下也會出現問題。

另外,我還發現我的operator=函數有問題,具體的問題請參見上面兩篇文章的operator=函數。此外,本實現還有一些問題沒有考慮:線程安全,if(智能指針)等。
天太晚了,所以就不排版了,請見諒!

posted on 2010-12-17 22:43 OnTheWay 閱讀(2955) 評論(3)  編輯 收藏 引用 所屬分類: 個人感悟

FeedBack:
# re: 一種基于引用計數機制的智能指針實現[未登錄]
2010-12-17 22:55 | hdqqq
比較討厭這種引用計數指針的使用,一旦使用就意味這在所有的函數參數中必須使用指針引用或者值拷貝,一旦某些函數要求用裸指針,就可能引發問題。  回復  更多評論
  
# re: 一種基于引用計數機制的智能指針實現
2010-12-18 20:38 | Phuehvk
Boost 里面有,在C++ TR1 里面也已經有這種指針(就是來自Boost)  回復  更多評論
  
# re: 一種基于引用計數機制的智能指針實現
2010-12-21 19:49 | 叫我老王吧
把A *p = new A();這句換成A p;不行嗎?  回復  更多評論
  

<2010年12月>
2829301234
567891011
12131415161718
19202122232425
2627282930311
2345678

常用鏈接

留言簿(4)

隨筆分類

隨筆檔案

友情連接

搜索

  •  

最新評論

閱讀排行榜

評論排行榜

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            亚洲精品乱码| 在线观看日韩av电影| 亚洲男人的天堂在线观看| 亚洲免费观看高清完整版在线观看| 欧美激情小视频| 亚洲一二三区精品| 午夜精品一区二区三区四区| 国产一区二区三区久久精品| 欧美激情bt| 国产精品久久久久aaaa九色| 亚久久调教视频| 久久久久青草大香线综合精品| 亚洲黄色av一区| 一区二区三区欧美激情| 国产三区二区一区久久| 欧美成人在线免费观看| 欧美视频在线观看视频极品| 久久综合久久综合九色| 欧美日产国产成人免费图片| 欧美怡红院视频一区二区三区| 久久久天天操| 性久久久久久久久久久久| 久久精品一区二区三区四区| 夜夜夜精品看看| 久久精品国产77777蜜臀| 日韩亚洲精品电影| 欧美在线播放一区二区| 一本久久综合亚洲鲁鲁| 久久精品91久久久久久再现| 亚洲一区二区黄色| 老**午夜毛片一区二区三区| 亚洲欧美一区二区原创| 欧美不卡视频一区发布| 欧美在线播放| 欧美视频精品在线| 欧美大胆人体视频| 一区二区精品在线| 亚洲经典在线看| 欧美一区二区国产| 亚洲欧美不卡| 欧美日韩一区在线观看| 欧美福利精品| 国模 一区 二区 三区| 99视频有精品| 夜夜爽av福利精品导航| 欧美 日韩 国产在线| 久久久爽爽爽美女图片| 国产欧美韩国高清| 亚洲小说区图片区| 亚洲手机成人高清视频| 欧美精品一级| 日韩午夜激情电影| 9l视频自拍蝌蚪9l视频成人| 男人插女人欧美| 欧美高清在线精品一区| 在线观看一区二区精品视频| 欧美一区日本一区韩国一区| 久久成人精品视频| 国产午夜精品视频免费不卡69堂| 一区二区三区欧美成人| 亚洲综合电影| 国产精品久久中文| 亚洲自拍高清| 久久久精品999| 今天的高清视频免费播放成人 | 日韩午夜电影av| 日韩午夜电影| 欧美日韩1区2区| 99精品热6080yy久久 | 黑人中文字幕一区二区三区 | 亚洲美女在线看| 亚洲图片自拍偷拍| 国产精品久久77777| 亚洲一线二线三线久久久| 欧美一区三区三区高中清蜜桃| 国产精品亚洲一区| 久久av一区二区| 欧美大片免费观看| 亚洲视频福利| 国产亚洲福利社区一区| 久久九九99| 亚洲精品美女久久7777777| 日韩一级片网址| 国产精品拍天天在线| 欧美中文日韩| 亚洲欧洲精品一区二区三区不卡 | 国内精品久久久久久久果冻传媒 | 久久激情五月激情| 亚洲激情自拍| 欧美在线免费播放| 亚洲欧洲另类| 国产精品免费网站| 免费亚洲一区| 亚洲一区自拍| 亚洲国内精品| 久久激情综合| 99精品久久免费看蜜臀剧情介绍| 亚洲一区二区三区影院| 乱码第一页成人| 一区二区三区www| 狠狠色综合日日| 欧美视频在线观看免费| 久久亚洲欧美| 亚洲免费在线观看视频| 亚洲国产精品一区二区久| 香蕉成人久久| av成人免费观看| 黄色成人片子| 国产精品亚洲综合| 欧美欧美天天天天操| 久久精品91久久久久久再现| 一区二区三区日韩在线观看| 免费在线观看日韩欧美| 欧美在线日韩在线| 亚洲一级黄色片| 亚洲日本在线观看| 一区二区三区在线视频免费观看 | 激情综合在线| 国产一区二区三区免费不卡| 欧美午夜精品久久久久久孕妇| 猛男gaygay欧美视频| 欧美伊人久久久久久久久影院| 一区二区三区成人精品| 亚洲国产精品久久久久婷婷884 | 久久黄色网页| 午夜在线电影亚洲一区| 亚洲视频免费看| av不卡免费看| 亚洲精品在线视频| 亚洲国产欧美一区二区三区丁香婷 | 麻豆精品91| 久久久美女艺术照精彩视频福利播放| 亚洲综合电影一区二区三区| 在线综合欧美| 亚洲一区二区三区精品动漫| 宅男噜噜噜66一区二区| 一区二区日韩欧美| 在线视频亚洲欧美| 99国产精品久久久久久久| 欧美一区二区三区喷汁尤物| 亚洲你懂的在线视频| 亚洲一区二区三区精品动漫| 一区二区高清在线观看| 亚洲少妇中出一区| 亚洲视频在线观看| 亚洲午夜一区| 亚洲欧美日韩在线不卡| 亚洲欧美影院| 久久久777| 麻豆精品在线播放| 欧美激情小视频| 亚洲日本成人| 亚洲天堂av图片| 亚洲欧美日韩电影| 久久精品国产亚洲一区二区三区 | 亚洲激情视频| 一区二区欧美在线观看| 性娇小13――14欧美| 欧美在线啊v| 欧美本精品男人aⅴ天堂| 欧美日韩国产高清| 国产午夜精品一区二区三区欧美 | 一本久道久久综合婷婷鲸鱼| 亚洲免费av电影| 亚洲欧美日韩区| 久久国产精品一区二区| 欧美承认网站| 亚洲视频999| 久久久久久久久久码影片| 欧美国产激情| 国产日本欧美一区二区三区| 亚洲国产综合在线看不卡| 亚洲欧美日韩第一区| 久久婷婷色综合| 日韩视频在线免费观看| 久久精品国产2020观看福利| 欧美日韩ab片| 在线观看成人小视频| 亚洲一区免费观看| 欧美成人免费大片| 亚洲尤物视频在线| 欧美国产三区| 国产亚洲一区二区精品| 一区二区三区www| 欧美aⅴ99久久黑人专区| 在线亚洲伦理| 欧美久色视频| 伊人久久成人| 欧美在线啊v| 一区二区欧美精品| 欧美大胆成人| 精品va天堂亚洲国产| 欧美一区观看| 一本综合精品| 欧美福利视频网站| 在线观看日韩av先锋影音电影院| 亚洲欧美日韩区| 一区二区三区视频在线播放| 免费在线国产精品| 伊人久久婷婷色综合98网|