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

C++ Programmer's Cookbook

{C++ 基礎} {C++ 高級} {C#界面,C++核心算法} {設計模式} {C#基礎}

auto_ptr(轉)

auto_ptr源碼 const auto_ptr保證擁有權不能轉移的實現原理?
-----------------------------------------------------------------------------------------------

在《C++標準程序庫》p55,提到了auto_ptr使用了一個技巧,能夠copy和復制non-const auto_ptr,但不可以copy和復制const atuo_ptr。
//auto_ptr的源碼:
template
struct auto_ptr_ref
{
    _Tp1* _M_ptr;
    
      explicit
      auto_ptr_ref(_Tp1* __p): _M_ptr(__p) { }
};


template
class auto_ptr
{
    private:
        _Tp* _M_ptr;
     
    public:
       typedef _Tp element_type;
     
       explicit
       auto_ptr(element_type* __p = 0) throw() : _M_ptr(__p) { }

       auto_ptr(auto_ptr& __a) throw() : _M_ptr(__a.release()) { }

       template
       auto_ptr(auto_ptr<_Tp1>& __a) throw() : _M_ptr(__a.release()) { }

       auto_ptr&
       operator=(auto_ptr& __a) throw()
       {
reset(__a.release());
return *this;
       }

       template
       auto_ptr&
       operator=(auto_ptr<_Tp1>& __a) throw()
       {
  reset(__a.release());
  return *this;
       }

       ~auto_ptr() { delete _M_ptr; }
     
       element_type&
       operator*() const throw()
       {
  _GLIBCXX_DEBUG_ASSERT(_M_ptr != 0);
  return *_M_ptr;
       }
     
       element_type*
       operator->() const throw()
       {
 _GLIBCXX_DEBUG_ASSERT(_M_ptr != 0);
 return _M_ptr;
       }
     
       element_type*
       get() const throw() { return _M_ptr; }
     
       element_type*
       release() throw()
       {
  element_type* __tmp = _M_ptr;
  _M_ptr = 0;
  return __tmp;
       }
     
       void
       reset(element_type* __p = 0) throw()
       {
 if (__p != _M_ptr)
 {
    delete _M_ptr;
    _M_ptr = __p;
 }
       }
     
       auto_ptr(auto_ptr_ref __ref) throw()
       : _M_ptr(__ref._M_ptr) { }
     
       auto_ptr&
       operator=(auto_ptr_ref __ref) throw()
       {
 if (__ref._M_ptr != this->get())
 {
    delete _M_ptr;
    _M_ptr = __ref._M_ptr;
 }
 return *this;
       }
     
      template
      operator auto_ptr_ref<_Tp1>() throw()
      { return auto_ptr_ref<_Tp1>(this->release()); }

      template
      operator auto_ptr<_Tp1>() throw()
      { return auto_ptr<_Tp1>(this->release()); }
};//VC7中的

---------------------------------------------------------------------------------------------------------------
// TEMPLATE CLASS auto_ptr
template
    class auto_ptr;

template
    struct auto_ptr_ref
        {    // proxy reference for auto_ptr copying
    auto_ptr_ref(auto_ptr<_Ty>& _Right)
        : _Ref(_Right)
        {    // construct from compatible auto_ptr
        }

    auto_ptr<_Ty>& _Ref;    // reference to constructor argument
    };

template
    class auto_ptr
        {    // wrap an object pointer to ensure destruction
public:
    typedef _Ty element_type;

    explicit auto_ptr(_Ty *_Ptr = 0) _THROW0()
        : _Myptr(_Ptr)
        {    // construct from object pointer
        }

    auto_ptr(auto_ptr<_Ty>& _Right) _THROW0()
        : _Myptr(_Right.release())
        {    // construct by assuming pointer from _Right auto_ptr
        }

    auto_ptr(auto_ptr_ref<_Ty> _Right) _THROW0()
        : _Myptr(_Right._Ref.release())
        {    // construct by assuming pointer from _Right auto_ptr_ref
        }

    template
        operator auto_ptr<_Other>() _THROW0()
        {    // convert to compatible auto_ptr
        return (auto_ptr<_Other>(*this));
        }

    template
        operator auto_ptr_ref<_Other>() _THROW0()
        {    // convert to compatible auto_ptr_ref
        return (auto_ptr_ref<_Other>(*this));
        }

    template
        auto_ptr<_Ty>& operator=(auto_ptr<_Other>& _Right) _THROW0()
        {    // assign compatible _Right (assume pointer)
        reset(_Right.release());
        return (*this);
        }

    template
        auto_ptr(auto_ptr<_Other>& _Right) _THROW0()
        : _Myptr(_Right.release())
        {    // construct by assuming pointer from _Right
        }

    auto_ptr<_Ty>& operator=(auto_ptr<_Ty>& _Right) _THROW0()
        {    // assign compatible _Right (assume pointer)
        reset(_Right.release());
        return (*this);
        }

    auto_ptr<_Ty>& operator=(auto_ptr_ref<_Ty>& _Right) _THROW0()
        {    // assign compatible _Right._Ref (assume pointer)
        reset(_Right._Ref.release());
        return (*this);
        }

    ~auto_ptr()
        {    // destroy the object
        delete _Myptr;
        }

    _Ty& operator*() const _THROW0()
        {    // return designated value
        return (*_Myptr);
        }

    _Ty *operator->() const _THROW0()
        {    // return pointer to class object
        return (&**this);
        }

    _Ty *get() const _THROW0()
        {    // return wrapped pointer
        return (_Myptr);
        }

    _Ty *release() _THROW0()
        {    // return wrapped pointer and give up ownership
        _Ty *_Tmp = _Myptr;
        _Myptr = 0;
        return (_Tmp);
        }

    void reset(_Ty* _Ptr = 0)
        {    // destroy designated object and store new pointer
        if (_Ptr != _Myptr)
            delete _Myptr;
        _Myptr = _Ptr;
        }

private:
    _Ty *_Myptr;    // the wrapped object pointer
    };
----------------------------------------------------------------------------------------------------------
C++中的auto_ptr (修改版本) stl 文件中的 std::auto_ptr 在C++中的故事特別多, 在它的演變過程中至少出現了3個版本.
http://www.josuttis.com/libbook/auto_ptr.html 這個連接里面有它完整的故事.
VC6中STL帶的auto_ptr( 帶owner字段)的版本應該就是文中說的Version 2.

最新的Version里面包含了一個auto_ptr_ref, 這個是當將auto_ptr作為函數返回值和函數參數時需要引入的
一個"額外間接層".

下面是它的一些說明:

auto_ptr的拷貝構造函數和一般我們常見的不同, 它的參數rhs并不是const reference, 而是refence,

auto_ptr( /*const */ auto_ptr& rhs)
{
  ...
}

假設我們需要將一個auto_ptr作為某個函數的返回值, 例如
auto_ptr source()
{
  return auto_ptr(new int(3));
}

那么我們如何在caller中得到返回的結果呢?
理所當然的語法是:
auto_ptr p( source() );     (拷貝構造函數)
或者
auto_ptr p = source();      (拷貝構造函數)
或者
auto_ptr p = ...;           (operator=)
p = source();


但是如果沒有auto_ptr_ref的存在, 上面這些行實際上應該是一個編譯錯誤(VC6不報錯), 原因是:

C++中有左值/右值之分, 函數如果返回值, 那么是r-value. 右值作為reference函數參數時, 只能是const reference.
因此source函數返回的auto_ptr作為rhs實參調用auto_ptr的拷貝構造函數時, 只能是const refernce, 但是
這個函數的簽名需要rhs為reference, 因此無法編譯.
舉個最簡單的例子:
有函數:
int foo() { return 0; }
void bar(int & i) { }
調用
int& i  = foo() ;       //錯誤
const int& i = foo();   //OK
bar(foo())              //錯誤

同理, 拷貝構造函數不過是一個特殊的"函數"而已, 我們上面的source函數返回的auto_ptr對象也只能作為一個
const auto_ptr&, 但是這個拷貝構造函數需要的參數原型是auto_ptr&, 而不是const auto_ptr& .
因此auto_ptr引入了一個'額外的間接層' auto_ptr_ref, 來完成一個從r-value到l-value之間的過渡.

基本的思路是;
提供另外一個構造函數, 接受一個以值傳遞的auto_ptr_ref:
auto_ptr( auto_ptr_ref ref)
{
      ....
}

然后在auto_ptr類中, 提供一個自動轉型的函數
operator auto_ptr_ref ()
{
    .....
}


這樣, source返回一個auto_ptr, 編譯器嘗試調用拷貝構造函數, 發(fā)現參數不必配(期望const), 然后發(fā)現了一個自動轉型的
operator auto_ptr_ref()函數, 而后又發(fā)現通過調用該自動轉型得到一個auto_ptr_ref對象后, 可以調用caller的
auto_ptr的以auto_ptr_ref為參數的非explicit的構造函數, 完成了一個auto_ptr到另外一個auto_ptr之間的復制過程.

注意一點: operator auto_ptr_ref () 不是const成員函數.
C++語法規(guī)則中對于臨時變量的r-value有個詭秘的地方就是:
如果你需要將r-value保存在一個reference中, 或者作為某個refence的函數參數, 那么必須為const reference,
但是你也可以在一個完整的表達式中直接使用這個臨時變量, 這種情況下該臨時變量實際上并不是作為const reference對待,
因為你可以調用它的非const成員函數. 例如:

class Integer
{
public:

  void zero() { i = 0; }

private:
  int i;
};


class Integer
{
public:

  void zero() { i = 0; }

private:
  int i;
};

Integer().zero();       //創(chuàng)建一個Integer的臨時變量, 然后調用非const成員函數.

這樣, auto_ptr p( source() );

實際上發(fā)生的事情就是:
 auto_ptr p( source().operator auto_ptr_ref());

通過source()函數得到一個臨時的auto_ptr對象, 然后調用其中的自動轉換函數得到一個auto_ptr_ref,
即使該轉型函數是非const成員函數仍然可行.

然后調用 p 對象的以auto_ptr_ref為參數的構造函數進行復制.
然后, source()函數創(chuàng)建的臨時對象在整個表達式結束后被析構, 當然這個時候這個臨時對象內部的指針已經被reset(0)了,
因為該指針的擁有權已經被p接管了. (否則會重復刪除)

std::auto_ptr在很多情況下是很便利的, 例如一個函數內部需要通過new分配一個結構, 那么誰來釋放是一個問題,
一種原則是誰分配, 誰釋放, 但是對于這種情況顯然不合適.
利用auto_ptr就簡單得多了: 誰擁有誰釋放, 誰都不要那么就編譯器自動釋放它. 例如

有個函數:
auto_ptr create_sth()
{
  auto_ptr p(new sth);
  return p;
}

調用1:
auto_ptr p = create_sth();
...
p退出作用域, 自動釋放.

調用2:
create_sth();
沒有人接受這個返回的對象, 那么編譯器自動會調用auto_ptr的析構函數釋放之.

sink也是一個作用:
例如我已經擁有一個auto_ptr對象的指針, 那么我可以定義一個sink函數, 原型如下:
void sink(auto_ptr p)
{
}

正如sink名字暗示的一樣, sink函數起到一個吸收作用, 將某個外部的auto_ptr對象吸收過來,類似于宇宙中的"黑洞".
例如:
  auto_ptr p(new sth);
  sink(p);
  //這里, p指向null了, p所指的sth對象已經被sink函數"吸收"了.

當然為了防止這種情況在你不注意的情況下發(fā)生, 你可以
const auto_ptr p(new sth);
sink(p); //編譯錯誤
auto_ptr p2 = p;        //編譯錯誤

這樣, 一個const auto_ptr的對象一旦構造完成, 永遠不會失去對該對象的擁有權. "一旦擁有, 從不失去".

當然auto_ptr最重要的作用, 也是它的原始目的是為了提供異常安全.


auto_ptr
動態(tài)內存使用最多的是在C++應用程序的代碼中。有過編程經驗的程序員雖然都知道new操作符的使用一定要與delete匹配,在某些場合仍然可能有內存溢出。當異常被擲出時,程序的正常控制流程被改變,因此導致潛在的內存溢出。例如, 
void g() //可能擲出
  {
    if (some_condition == false)
      throw X();
  }
  void func()
  {
    string * pstr = new string;
    g(); //如果 g 擲出一個異常,內存溢出
    delete pstr; //如果 g 擲出一個異常,則此行為不能達到的代碼行。
  }
  int main()
  {
    try
    {
      func();
    }
    catch(...)
    {}
  }
 
    當 g 擲出一個異常,異常處理機制展開堆棧:g()退出,同時控制被轉移到 main() 的 catch(...)代碼塊。這時,無論怎樣,func()中的delete語句都不會被執(zhí)行,由此導致pstr的內存溢出。要是使用局部自動串變量,而不是使用動態(tài)分配-內存溢出就不會出現了:

string str; //局部自動對象
g(); //沒有內存溢出 
    許多數據重要的結構以及應用,象鏈表,STL容器,串,數據庫系統(tǒng)以及交互式應用必須使用動態(tài)內存分配,因此仍然冒著萬一發(fā)生異常導致內存溢出的風險。C++標準化委員會意識到了這個漏洞并在標準庫中添加了一個特殊的類模板,它就是std::auto_ptr,其目的是促使動態(tài)內存和異常之前進行平滑的交互。Auto_ptr保證當異常擲出時分配的對象(即:new操作符分配的對象)能被自動銷毀,內存能被自動釋放。下面我們就來討論使用動態(tài)內存時,如何正確和有效地使用auto_ptr來避免資源溢出。這個技術適用于文件,線程,鎖定以及與此類似的資源。

    Auto_ptr的定義可以在中找到。與標準庫中其它的成員一樣,它被聲明在命名空間std::中。當你實例化auto_ptr對象時,對它進行初始化的方法是用一個指針指向動態(tài)分配的對象,下面是實例化和初始化auto_ptr對象的例子: 
include
  #include
  using namespace std;
  void func()
  {
    auto_ptr pstr (new string); /* 創(chuàng)建并初始化auto_ptr */
  }
 
    auto_ptr后面的尖括弧里指定auto_ptr指針的類型,在這個例子中是string。然后auto_ptr句柄的名字,在這個例子中是pstr。最后是用動態(tài)分配的對象指針初始化這個實例。注意你只能使用auto_ptr構造器的拷貝,也就是說,下面的代碼是非法的: 
auto_ptr pstr  = new string; //編譯出錯
 
    Auto_ptr是一個模板,因此它是完全通用的。它可以指向任何類型的對象,包括基本的數據類型: 
auto_ptr pi  (new int);
 
    一旦你實例化一個auto_ptr,并用動態(tài)分配的對象地址對它進行了初始化,就可以將它當作普通的對象指針使用,例如: 
*pstr = "hello world"; //賦值
  pstr->size(); //調用成員函數
 
    之所以能這樣做是因為auto_ptr重載了操作符&,*和->。不要被語法誤導,記住pstr是一個對象,不是一個指針。

    auto_ptr是如何解決前面提到的內存溢出問題呢?auto_ptr的析構函數自動摧毀它綁定的動態(tài)分配對象。換句話說,當pstr的析構函數執(zhí)行時,它刪除構造pstr期間創(chuàng)建的串指針。你絕不能刪除auto_ptr,因為它是一個本地對象,它的析構函數是被自動調用的。讓我們看一下函數func()的修訂版本,這次使用了auto_ptr: 
void func()
  {
    auto_ptr  pstr (new string);
    g();  //如果g()擲出異常,pstr 被自動摧毀
  }
 
    C++保證在堆棧展開過程中,自動存儲類型的對象被自動摧毀。因此,如果g()擲出異常,pstr的析構函數將會在控制被轉移到catch(...)塊之前執(zhí)行。因為pstr的析構函數刪除其綁定的串指針,所以不會有內存溢出發(fā)生。這樣我們在使用動態(tài)分配對象時,利用auto_ptr就實現了自動和安全的本地對象。

如何避免使用auto_ptr的缺陷

    auto_ptr并不是完美無缺的,它的確很方便,但也有缺陷,在使用時要注意避免。首先,不要將auto_ptr對象作為STL容器的元素。C++標準明確禁止這樣做,否則可能會碰到不可預見的結果(在另文中討論)。

    auto_ptr的另一個缺陷是將數組作為auto_ptr的參數: 
auto_ptr  pstr (new char[12] ); //數組;為定義
 
    記住不管什么時候使用數組的new操作時,必須要用delete[]來摧毀數組。因為auto_ptr的析構函數只對非數組類型起作用。所以數組是不能被正確摧毀的話,程序的行為是不明確的。總之,auto_ptr控制一個由new分配的單對象指針,僅此而已。 
--------------------------------------------------------------------------------------------------
Misusing auto_ptrs

auto_ptrs satisfy a certain need; namely, to avoid resource leaks when exception handling is used. Unfortunately, the exact behavior of auto_ptrs changed in the past and no other kind of smart pointers are provided in the C++ standard library, so people tend to misuse auto_ptrs. Here are some hints to help you use them correctly:

  1. auto_ptrs cannot share ownership.

    An auto_ptr must not refer to an object that is owned by another auto_ptr (or other object). Otherwise, if the first pointer deletes the object, the other pointer suddenly refers to a destroyed object, and any further read or write access may result in disaster.

  2. auto_ptrs are not provided for arrays.

    An auto_ptr is not allowed to refer to arrays. This is because an auto_ptr calls delete instead of delete [] for the object it owns. Note that there is no equivalent class in the C++ standard library that has the auto_ptr semantics for arrays. Instead, the library provides several container classes to handle collections of data (see Chapter 5).

  3. auto_ptrs are not "universal smart pointers."

    An auto_ptr is not designed to solve other problems for which smart pointers might be useful. In particular, they are not pointers for reference counting. (Pointers for reference counting ensure that an object gets deleted only if the last of several smart pointers that refer to that object gets destroyed.)

  4. auto_ptrs don't meet the requirements for container elements.

    An auto_ptr does not meet one of the most fundamental requirements for elements of standard containers. That is, after a copy or an assignment of an auto_ptr, source and sink are not equivalent. In fact, when an auto_ptr is assigned or copied, the source auto_ptr gets modified because it transfers its value rather than copying it. So you should not use an auto_ptr as an element of a standard container. Fortunately, the design of the language and library prevents this misuse from compiling in a standard-conforming environment.

posted on 2005-11-09 12:34 夢在天涯 閱讀(1692) 評論(0)  編輯 收藏 引用 所屬分類: CPlusPlus

公告

EMail:itech001#126.com

導航

統(tǒng)計

  • 隨筆 - 461
  • 文章 - 4
  • 評論 - 746
  • 引用 - 0

常用鏈接

隨筆分類

隨筆檔案

收藏夾

Blogs

c#(csharp)

C++(cpp)

Enlish

Forums(bbs)

My self

Often go

Useful Webs

Xml/Uml/html

搜索

  •  

積分與排名

  • 積分 - 1812153
  • 排名 - 5

最新評論

閱讀排行榜

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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| 亚洲精品国产视频| 99国产成+人+综合+亚洲欧美| 午夜在线播放视频欧美| 亚洲精品欧洲精品| 欧美99在线视频观看| 黄色成人片子| 久久久五月天| 欧美影视一区| 国产一区二区成人久久免费影院| 国产精品99久久久久久久vr| 蜜臀久久99精品久久久画质超高清 | 亚洲专区在线视频| 欧美日本亚洲| 亚洲精品无人区| 欧美色另类天堂2015| 国产精品一区二区a| 99热这里只有精品8| 亚洲国产成人精品久久久国产成人一区| 欧美一区免费| 黑人一区二区| 牛牛影视久久网| 蜜乳av另类精品一区二区| 在线观看日韩国产| 亚洲成色777777在线观看影院| 久久全球大尺度高清视频| 久久综合狠狠| 亚洲精品久久久久久下一站 | 美国成人毛片| 麻豆国产精品va在线观看不卡| 一色屋精品亚洲香蕉网站| 久久精品夜色噜噜亚洲a∨ | 老司机一区二区| 欧美一级免费视频| 久久国产乱子精品免费女| 小辣椒精品导航| 国内成人精品视频| 欧美精品久久久久久久久老牛影院 | 久久影院午夜论| 宅男在线国产精品| 亚洲欧美日本国产专区一区| 国产精品午夜电影| 久久久人成影片一区二区三区 | 欧美视频在线观看 亚洲欧| 欧美电影免费观看| 一区二区91| 亚洲一区二区视频在线观看| 国产日产欧产精品推荐色| 午夜亚洲精品| 老牛嫩草一区二区三区日本| 亚洲久久一区| 性欧美激情精品| 亚洲欧洲综合另类| 亚洲天堂av在线免费观看| 一区免费视频| 在线中文字幕一区| 亚洲午夜精品一区二区| 久久天天狠狠| 亚洲人成人77777线观看| 妖精视频成人观看www| 黄网站免费久久| 亚洲美女视频网| 极品少妇一区二区三区精品视频| 亚洲国产精品久久久久秋霞不卡| 国产精品福利影院| 欧美激情第二页| 国产精品资源| 欧美黄免费看| 国产中文一区| 欧美在线播放| 亚洲一区二区三区国产| 久久婷婷国产综合国色天香| 亚洲欧美成人一区二区在线电影| 欧美国产欧美综合| 夜夜嗨av色综合久久久综合网| 久久久久久久久久久久久女国产乱| 一本久久综合| 亚洲国产欧美另类丝袜| 亚洲一区二区三区四区五区黄| 久久久国产精彩视频美女艺术照福利| 欧美在线三级| 一区二区免费在线观看| 久久久国产精品一区二区中文| 亚洲激情在线| 免费成人av在线看| 国内外成人免费激情在线视频| 国产精品嫩草影院av蜜臀| 欧美77777| 欧美激情片在线观看| 日韩视频三区| 午夜国产一区| 尤妮丝一区二区裸体视频| 亚洲免费观看高清在线观看| 国产精品国码视频| 国产精品毛片va一区二区三区| 亚洲人成77777在线观看网| 久久久久久九九九九| 亚洲图片欧美午夜| 久久不射2019中文字幕| 欧美精品一区二区三区视频| 国产日本欧美在线观看| 亚洲精品四区| 嫩草成人www欧美| 99精品国产在热久久| 99精品视频一区二区三区| 久久久人人人| 鲁大师成人一区二区三区| 欧美日韩伦理在线| 亚洲欧美精品中文字幕在线| 亚洲国产精品成人一区二区| 亚洲精品一区二区三区福利| 亚洲激情成人在线| 国产一区二区久久精品| 一区二区三区视频在线观看| 浪潮色综合久久天堂| 亚洲国产婷婷香蕉久久久久久| 国产精品久久波多野结衣| 国产欧美另类| 国产精品欧美精品| 久久久国产视频91| 欧美福利一区| 噜噜噜躁狠狠躁狠狠精品视频 | 国产精品久久91| 蜜桃伊人久久| 国产精品制服诱惑| 亚洲精品视频二区| 好吊日精品视频| 国产精品99久久不卡二区| 亚洲黄色在线看| 亚洲一区二区在线免费观看| 在线观看日韩| 欧美一区成人| 亚洲视频香蕉人妖| 欧美大片91| 男男成人高潮片免费网站| 国产精品视频久久久| 亚洲理论电影网| 亚洲理伦在线| 久久色在线观看| 国产精品每日更新| 久久国产精品一区二区三区四区| 欧美高清视频在线播放| 老巨人导航500精品| 国产亚洲欧美日韩在线一区| 亚洲最新色图| 亚洲香蕉视频| 欧美系列亚洲系列| 亚洲精品男同| 亚洲精品久久久蜜桃| 女女同性精品视频| 亚洲国产二区| 亚洲香蕉伊综合在人在线视看| 免费在线亚洲欧美| 欧美肥婆bbw| 欧美日韩一区二区视频在线| 亚洲伦理在线| 亚洲一区日韩在线| 国产精品yjizz| 亚洲性感激情| 久久国内精品视频| 激情欧美一区二区三区| 久久国产精品久久w女人spa| 欧美va天堂va视频va在线| 久久精品一区二区三区中文字幕| 女主播福利一区| 亚洲青涩在线| 国产精品毛片一区二区三区| 亚洲综合第一| 久久久噜噜噜久久狠狠50岁| 国产精品手机在线| 亚洲欧美在线播放| 久久精彩视频| 快播亚洲色图| 亚洲精品综合精品自拍| 欧美一级理论片| 国产婷婷精品| 国产精品一香蕉国产线看观看| 欧美午夜在线一二页| 亚洲国产色一区| 亚洲一区二区三区四区中文| 欧美刺激午夜性久久久久久久| 麻豆精品精华液| 国产在线精品自拍| 欧美日韩亚洲一区二| 免费亚洲电影在线| 欧美一区视频| 免费久久99精品国产自| 老司机精品视频一区二区三区| 狠狠干成人综合网| 久久婷婷国产综合精品青草| 久久网站热最新地址| 国产亚洲欧美激情| 亚洲午夜未删减在线观看| 欧美一区2区三区4区公司二百| 日韩一级大片在线| 国产精品美女久久久|