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

MyMSDN

MyMSDN記錄開發新知道

[翻譯]高效使用auto_ptr

本文來自C/C++用戶日志,17(10),1999年10月  原文鏈接

大部分人都聽說過auto_ptr指針,但是并非所有人都每天使用它。不使用它是不明智的(可恥的),因為auto_ptr的設計初衷是為了解決C++設計和編碼的普遍問題,將它用好可以寫出更健壯的代碼。本文指出如何正確使用auto_ptr以使程序變得安全,以及如何避開危險,而不是一般使用auto_ptr的惡習所致的創建間歇性和難以診斷的問題。

為什么它是一個“自動”指針

auto_ptr只是許許多多智能指針中的一種。許多商業庫提供許多更強大的智能指針,可以完成更多的事情。從可以管理引用計數到提供更先進的代理服務等。應該把auto_ptr認為是智能指針中的福特Escort[注釋]:一個基于簡單且通用目的的智能指針,既沒有小發明也沒有豐富的特殊目的更不需要高性能,但是能將許多普通的事情做好,并且能夠適合日常使用的智能指針。

auto_ptr做這樣一件事:擁有一個動態分配內存對象,并且在它不再需要的時候履行自動清理的職責。這里有個沒有使用auto_ptr指針的不安全的例子:

    // Example 1(a): Original code
    //
    void f()
    {
      T* pt( new T );

      /*...more code...*/

      delete pt;
    }

我們每天都像這樣寫代碼,如果f()只是一個三行程序,也沒做什么多余的事情,這樣做當然可以很好工作。但是如果f()沒有執行delete語句,比如程序提前返回(return)了,或者在執行的時候拋出異常了,然后就導致已經分配的對象沒有被刪除,因此我們就有了一個經典的內存泄漏。

一個使Example(1)安全的辦法是用一個“智能”的指針擁有這個指針,當銷毀的時候,刪除那個被指的自動分配的對象。因為這個智能指針被簡單地用為自動對象(這就是,當它離開它的作用域的時候自動銷毀對象),所以它被稱作“自動”指針。

    // Example 1(b): Safe code, with auto_ptr
    //
    void f()
    {
      auto_ptr<T> pt( new T );

      /*...more code...*/

    } // cool: pt's destructor is called as it goes out
      // of scope, and the object is deleted automatically

現在這段代碼將不會再T對象上發生泄漏了,不必在意這個方法是正常退出還是異常退出,因為pt的析構函數將總是在堆棧彈出的時候被調用。清理工作將自動進行。

最后,使用auto_ptr和使用內建指針一樣地容易,如果要“收回”資源并且再次手動管理的話,我們可以調用release():

    // Example 2: Using an auto_ptr
    //
    void g()
    {
      T* pt1 = new T;
      // right now, we own the allocated object

      // pass ownership to an auto_ptr
      auto_ptr<T> pt2( pt1 );

      // use the auto_ptr the same way
      // we'd use a simple pointer
      *pt2 = 12;       // same as "*pt1 = 12;"
      pt2->SomeFunc(); // same as "pt1->SomeFunc();"

      // use get() to see the pointer value
      assert( pt1 == pt2.get() );

      // use release() to take back ownership
      T* pt3 = pt2.release();

      // delete the object ourselves, since now
      // no auto_ptr owns it any more
      delete pt3;

    } // pt2 doesn't own any pointer, and so won't
      // try to delete it... OK, no double delete

最后,我們可以使用auto_ptr的reset()方法將auto_ptr重置向另一個對象。如果auto_ptr已經獲得一個對象,這個過程就像是它先刪除已經擁有的對象,因此調用reset(),就像是先銷毀了auto_ptr,然后重建了一個新的并擁有該新對象:

    // Example 3: Using reset()
    //
    void h()
    {
      auto_ptr<T> pt( new T(1) );

      pt.reset( new T(2) );
        // deletes the first T that was
        // allocated with "new T(1)"

    } // finally, pt goes out of scope and
      // the second T is also deleted

包裝指針數據成員

同樣,auto_ptr也可以被用于安全地包裝指針數據成員??紤]下面使用Pimpl idiom(或者,編譯器防火墻)的例子:[1]

    // Example 4(a): A typical Pimpl
    //

    // file c.h
    //
    class C
    {
    public:
      C();
      ~C();
      /*...*/
    private:
      class CImpl; // forward declaration
      CImpl* pimpl_;
    };

    // file c.cpp
    //
    class C::CImpl { /*...*/ };

    C::C() : pimpl_( new CImpl ) { }
    C::~C() { delete pimpl_; }

簡單地說,就是C的私有細節被實現為一個單獨的對象,藏匿于一個指針之中。該思路要求C的構造函數負責為隱藏在類內部的輔助“Pimpl”對象分配內存,并且C的析構函數負責銷毀它。使用auto_ptr,我們會發現這非常容易:

    // Example 4(b): A safer Pimpl, using auto_ptr
    //

    // file c.h
    //
    class C
    {
    public:
      C();
      /*...*/
    private:
      class CImpl; // forward declaration
      auto_ptr<CImpl> pimpl_;
    };

    // file c.cpp
    //
    class C::CImpl { /*...*/ };

    C::C() : pimpl_( new CImpl ) { }

現在,析構函數不需要擔心刪除pimpl_指針了,因為auto_ptr將自動處理它。事實上,如果沒有其它需要顯式寫析構函數的原因,我們完全不需要自定義析構函數。顯然,這比手動管理指針要容易得多,并且將對象所有權包含進對象是一個不錯的習慣,這正是auto_ptr所擅長的。我們將在最后再次回顧這個例子。

所有權,源,以及調用者(Sinks)

它本身很漂亮,并且做得非常好:從函數傳入或傳出auto_ptrs,是非常有用的,比如函數的參數或者返回值。

讓我們看看為什么,首先我們考慮當拷貝auto_ptr的時候會發生什么:一個auto_ptr獲得一個擁有指針的對象,并且在同一時間只允許有一個auto_ptr可以擁有這個對象。當你拷貝一個auto_ptr的時候,你自動將源auto_ptr的所有權,傳遞給目標auto_ptr;如果目標auto_ptr已經擁有了一個對象,這個對象將先被釋放。在拷貝完之后,只有目標auto_ptr擁有指針,并且負責在合適的時間銷毀它,而源將被設置為空(null),并且不能再被當作原有指針的代表來使用。

例如:

    // Example 5: Transferring ownership from
    //            one auto_ptr to another
    //
    void f()
    {
      auto_ptr<T> pt1( new T );
      auto_ptr<T> pt2;

      pt1->DoSomething(); // OK

      pt2 = pt1;  // now pt2 owns the pointer,
                  // and pt1 does not

      pt2->DoSomething(); // OK

    } // as we go out of scope, pt2's destructor
      // deletes the pointer, but pt1's does nothing

但是要避免陷阱再次使用已經失去所有權的auto_ptr:

    // Example 6: Never try to do work through
    //            a non-owning auto_ptr
    //
    void f()
    {
      auto_ptr<T> pt1( new T );
      auto_ptr<T> pt2;

      pt2 = pt1;  // now pt2 owns the pointer, and
                  // pt1 does not

      pt1->DoSomething();
                  // error! following a null pointer
    }

謹記于心,我們現在看看auto_ptr如何在源和調用者之間工作?!霸础边@里是指一個函數,或者其它創建一個新資源的操作,并且通常將移交出資源的所有權。一個“調用者”函數反轉這個關系,也就是獲得已經存在對象的所有權(并且通常還負責釋放它)。而不是有一個源和調用者,返回并且利用一個禿頭指針(譯者注:而不是使用一個局部變量來傳遞這個指針),雖然,通過一個禿頭指針來獲得一個資源通常很好:

    // Example 7: Sources and sinks
    //

    // A creator function that builds a new
    // resource and then hands off ownership.
    //
    auto_ptr<T> Source()
    {
      return auto_ptr<T>( new T );
    }

    // A disposal function that takes ownership
    // of an existing resource and frees it.
    //
    void Sink( auto_ptr<T> pt )
    {
    }

    // Sample code to exercise the above:
    auto_ptr<T> pt( Source() ); // takes ownership

注意下面的微妙的變化:

  1. Source()分配了一個新對象并且以一個完整安全的方式將它返回給調用者,并讓調用者成為指針的擁有著。即使調用者忽略了返回值(顯然,如果調用者忽略了返回值,你應該從來沒有寫過代碼來刪除這個對象,對吧?),分配的對象也將被自動安全地刪除。

    在本文的最后,我將演示返回一個auto_ptr是一個好習慣。讓返回值包裹進一些東西比如auto_ptr通常是使得函數變得強健的有效方式。

  2. Sink()通過傳值的方式獲得對象所有權。當執行完Sink()的時候,當離開作用域的時候,刪除操作將被執行(只要Sink()沒有將所有權轉移)。上面所寫的Sink()函數實際上并沒有對參數做任何事情,因此調用“Sink(pt);”就等于寫了“pt.reset(0);”,但是大部分的Sink函數都將在釋放它之前做一些工作。

不可以做的事情,以及為什么不能做

謹記:千萬不要以我之前沒有提到的方式使用auto_ptrs。我已經看見過很多程序員試著用其他方式寫auto_ptrs就像他們在使用其它對象一樣。但問題是auto_ptr并不像其他對象。這里有些基本原則,我將把它們提出來以引起你的注意:

For auto_ptr, copies are NOT equivalent. (復制auto_ptr將與原來的不相等)

當你試著在一般的代碼中使用auto_ptrs的時候,它將執行拷貝,并且沒有任何提示,拷貝是不相等的(結果,它確實就是拷貝)??聪旅孢@段代碼,這是我在C++新聞組經??匆姷模?

    // Example 8: Danger, Will Robinson!
    //
    vector< auto_ptr<T> > v;

    /* ... */

    sort( v.begin(), v.end() );

在標準容器中使用auto_ptrs總是不安全的。一些人可能要告訴你,他們的編譯器或者類庫能夠很好地編譯它們,而另一些人則告訴你在某一個流行的編譯器的文檔中看到這個例子,不要聽他們的。

問題是auto_ptr并不完全符合一個可以放進容器類型的前提,因為拷貝auto_ptrs是不等價的。首先,沒有任何東西說明,vector不能決定增加并制造出“擴展”的內部拷貝。再次,當你調用一個一般函數的時候,它可能會拷貝元素,就像sort()那樣,函數必須有能力假設拷貝是等價的。至少一個流行的排序拷貝“核心”的元素,如果你試著讓它與auto_ptrs一起工作的話,它將拷貝一份“核心”的auto_ptr對象(因此轉移所有權并且將所有權轉移給一個臨時對象),然后對其余的元素也采取相同的方式(從現有成員創建更多的擁有所有權的auto_ptr),當排序完成后,核心元素將被銷毀,并且你將遇到一個問題:這組序列里至少一個auto_ptr(也就是剛才被掉包的那個核心元素)不再擁有對象所有權,而那個真實的指針已經隨著臨時對象的銷毀而被刪除了!

于是標準委員會回退并希望做一些能夠幫助你避免這些行為的事情:標準的auto_ptr被故意設計成當你希望在使用標準容器的時候使用它時打斷你(或者,至少,在大部分的標準庫實現中打斷你)。為了達到這個目的,標準委員會利用這樣一個技巧:讓auto_ptr's的拷貝構造函數和賦值操作符的右值(rhs)指向非常量。因為標準容器的單元素insert()函數,需要一個常量作為參數,因此auto_ptrs在這里就不工作了。(譯者注:右值不能賦值給非常量)

使用const auto_ptr是一個好習慣

將一個auto_ptr設計成const auto_ptrs將不再丟失所有權:拷貝一個const auto_ptr是違法的(譯者注:沒有這樣的構造函數),實際上你可以針對它做的唯一事情就是通過operator*()或者operator->()解引用它或者調用get()來獲得所包含的指針的值。這意味著我們有一個簡單明了的風格來表達一個絕不丟失所有權的auto_ptr:

    // Example 9: The const auto_ptr idiom
    //
    const auto_ptr<T> pt1( new T );
        // making pt1 const guarantees that pt1 can
        // never be copied to another auto_ptr, and
        // so is guaranteed to never lose ownership

    auto_ptr<T> pt2( pt1 ); // illegal
    auto_ptr<T> pt3;
    pt3 = pt1;              // illegal
    pt1.release();          // illegal
    pt1.reset( new T );     // illegal

這就是我要說的cosnt!因此如果現在你要向世界證明你的auto_ptr是不會被改變并且將總是刪除其所有權,加上const就是你要做的。const auto_ptr風格是有用的,你必須將它謹記于心。

auto_ptr以及異常安全

最后,auto_ptr對寫出異常安全的代碼有時候非常必要,思考下面的代碼:

    // Example 10(a): Exception-safe?
    //
    String f()
    {
      String result;
      result = "some value";
      cout << "some output";
      return result;
    }

該函數有兩個可見的作用:它輸出一些內容,并且返回一個String。關于異常安全的詳細說明超出了本文的范圍[2],但是我們想要取得的目標就是強異常安全的保障,歸結為確保函數的原子性——如果有異常,所有的作用一起發生或者都不發生。

雖然在例10(a)中的代碼非常精巧,看起來相當接近于異常安全的代碼,但仍然有一些小的瑕疵,就像下面的客戶代碼所示:

    String theName;
    theName = f();

因為結果通過值返回,因此String的拷貝構造函數將被調用,而拷貝賦值操作符被調用來將結果拷貝到theName中。如果任何一個拷貝失敗了,f()就完成了所有它的工作以及所有它的任務(這很好),但是結果是無法挽回的(哎喲我的媽呀)

我們可以做的更好嗎,是否可以通過避免拷貝來避免這個問題?例如,我們可以 讓函數有一個非常量引用參數并向下面這樣返回值:

    // Example 10(b): Better?
    //
    void f( String& result )
    {
      cout << "some output";
      result = "some value";
    }

這看起來很棒,但實際不是這樣的,返回result的賦值的函數只完成了一個功能,而將其它事情留給了我們。它仍然會出錯。因此這個做法不可取。

解決這個問題的一個方法是返回一個指向動態分配指針的String對象,但是最好的解決方案是讓我們做的更多,返回一個指針包含在auto_ptr:

    // Example 10(c): Correct (finally!)
    //
    auto_ptr<String> f()
    {
      auto_ptr<String> result = new String;
      *result = "some value";
      cout << "some output";
      return result;  // rely on transfer of ownership;
                      // this can't throw
    }

這里是一個技巧,當我們有效隱藏所有的工作來構造第二個功能(返回值)當確保它可以被安全返回給調用者并且在第一個功能(打印消息)完成的時候沒有拋出操作。我們知道一旦cout完成,返回值將成功交到調用者手中,并且無論如何都會正確清理:如果調用者接受返回值,調用者將得到這個拷貝的auto_ptr臨時對象的所有權;如果調用者沒有接受返回值,也就是忽略返回值,分配的String將在臨時auto_ptr被銷毀的時候自動清理。這種安全擴展的代價呢?就像我們經常實現的強異常安全一樣,強安全通常消耗一些效率(通常比較?。@里指額外的動態內存分配。但是當我們在效率和正確性之間做出選擇的話,我們通常會選擇后者!

讓我們養成在日常工作中使用auto_ptr的習慣。auto_ptr解決了常見的問題,并且能夠使你的代碼變得更安全和健壯,特別是它可以防止內存泄漏以及確保強安全。因為它是標準的,因此它在不同類庫和平臺之間是可移植的,因此無論你在哪里使用它,它都將是對的。

致謝

This article is drawn from material in the new book Exceptional C++: 47 engineering puzzles, programming problems, and exception-safety solutions by Herb Sutter, ? 2000 Addison Wesley Longman Inc., which contains further detailed treatments of points touched on briefly in this article, including exception safety, the Pimpl (compiler-firewall) Idiom, optimization, const-correctness, namespaces, and other C++ design and programming topics.

注釋

  1. Pimpl風格可以有效減少項目構建時間,因為它在C私有部分改變的時候,阻止客戶代碼引起廣泛的重新編譯。更多關于Pimpl風格以及如何部署編譯器墻,參考這本Exceptional C++的條款26到30。(Addison-Wesley, 2000)

  2. See the article originally published in C++ Report and available on the Effective C++ CD (Scott Meyers, Addison-Wesley, 1999) and Items 8 to 19 in Exceptional C++ (Herb Sutter, Addison-Wesley, 2000).

posted on 2010-04-07 19:08 volnet 閱讀(3681) 評論(10)  編輯 收藏 引用 所屬分類: 知識庫(KnowledgeLibrary) 、C/C++

評論

# re: [翻譯]高效使用auto_ptr 2010-04-07 20:05 giscn

最好遠離 auto_ptr, 這個東西引進來的問題比解決的問題多  回復  更多評論   

# re: [翻譯]高效使用auto_ptr 2010-04-07 20:32 唐風

@giscn
給些例子或是一些鏈接不咧
我贊同本文的觀點,但同時很想知道“遠離 auto_ptr” 的理由是否也能說明我。

謝謝了。

  回復  更多評論   

# re: [翻譯]高效使用auto_ptr 2010-04-08 13:02 Benjamin

什么時候用?該怎樣用?這是關鍵  回復  更多評論   

# re: [翻譯]高效使用auto_ptr 2010-04-08 13:40 giscn

首先如果要解決語句局部的內存自動回收,auto_ptr 采用了RAII的做法,這樣很好,應該就到此為止,那些reset, release函數都不必引入,使用也很簡單。
但是:auto_ptr很顯然想解決更廣范圍的內存回收,比如:一個指針在多個容器里,因此它引入了“所有權”、“源”這幾個概念,其實,有COM開發的經驗的人應該很熟悉這個概念,典型的,BSTR的創建與銷毀規則就是這種思路,這個概念帶來的麻煩COM開發人員是清楚的,我覺得歸根結底,在這種情況下,所有權不是那么容易分辨,舉例說明一下:一個指針保存在兩個容器中,那么哪一個是有所有權呢?更糟糕的是auto_ptr利用了常用的賦值語義來確定所有權,首先,它改變了賦值操作的習慣,常規的,a=b之后,b依然是有效的,而 auto_ptr卻讓b是無效的,這個就是是問題的根源。
其所要解決的問題根本沒有解決,你依然無法確定指針的所有權應該在那個容器中、何時銷毀。即使你清楚地知道,一個小的疏忽:賦值的順序就會引入bug。
好與不好,自己實踐、體會最重要。  回復  更多評論   

# re: [翻譯]高效使用auto_ptr 2010-04-08 14:10 volnet

@Benjamin
這就是這篇文章的主題啊,除了之前提到過的幾種形式,就不應該發明其它形式了……  回復  更多評論   

# re: [翻譯]高效使用auto_ptr 2010-04-09 03:22 欲三更

我覺得auto_ptr是C++里面典型的“因為設想太過宏偉,從而產生問題”的范例。

事實上大多數人為什么會想到用一個包裝過的指針?害怕內存泄漏。那么我們需要的就是一個確定會在某一個域結束時把自身攜帶對象析構掉的指針,就這么簡單。那么我們就實現一個沒有賦值功能的auto_ptr就好了,一了百了。

而且我覺得這里面有一個邏輯問題:假設我們在大括號開始處建立一個攜帶對象的指針,并且確定在大括號結束的時候對象會析構掉,那我們有什么理由把它傳遞給大括號之外的代碼呢?  回復  更多評論   

# re: [翻譯]高效使用auto_ptr 2010-04-09 10:42 volnet

@欲三更
這就是應該象是:
// stack <- dumb pointer
// dump pointer -> do()
// dump pointer -> hello();
// stack -> delete dumb pointer auto

該干嘛讓他自己干嘛去,我們要做的無非就是將指針在開始的時候交給棧可管理的對象去管理……然后繼續放任自由……  回復  更多評論   

# re: [翻譯]高效使用auto_ptr 2010-04-10 04:07 dui

please use smart pointer  回復  更多評論   

# re: [翻譯]高效使用auto_ptr 2010-04-12 00:12 anonymous

認識auto_ptr的作用及局限性,合理使用。不要動不動就遠離,不存在一個完美的東西可以解決所有的問題。  回復  更多評論   

# re: [翻譯]高效使用auto_ptr 2010-08-29 17:32 evening dresses

都每天使用它  回復  更多評論   

特殊功能
 
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            亚洲欧美成人一区二区三区| 久久亚洲私人国产精品va| 在线亚洲成人| 亚洲第一页在线| 欧美一区二区视频观看视频| 亚洲视频网在线直播| 亚洲日本中文字幕免费在线不卡| 国产日韩欧美日韩| 国产亚洲欧美日韩在线一区| 国产综合色在线| 亚洲精品欧洲精品| 亚洲深夜福利| 久久久久久一区二区| 欧美激情影院| 亚洲伊人第一页| 女人香蕉久久**毛片精品| 欧美精品一区二区在线播放| 国产精品日韩电影| 亚洲黄色影院| 久久精品亚洲精品国产欧美kt∨| 美女精品视频一区| 亚洲欧美日韩精品在线| 欧美成人午夜激情| 伊人夜夜躁av伊人久久| 欧美伊久线香蕉线新在线| 最近中文字幕mv在线一区二区三区四区 | 日韩网站在线看片你懂的| 亚洲午夜激情网站| 亚洲国产精品久久久久秋霞影院| 亚洲综合精品自拍| 欧美吻胸吃奶大尺度电影| 伊伊综合在线| 久久久青草婷婷精品综合日韩 | 亚洲精品欧洲| 欧美高清视频www夜色资源网| 亚洲大片一区二区三区| 免费久久精品视频| 裸体丰满少妇做受久久99精品| 很黄很黄激情成人| 久久久久久亚洲精品不卡4k岛国| 亚洲欧美综合国产精品一区| 国产精品一级| 免费在线一区二区| 欧美激情国产日韩| 亚洲欧美久久久久一区二区三区| 日韩视频在线你懂得| 国产精品一区视频网站| 久久久www成人免费无遮挡大片| 欧美亚洲综合在线| 亚洲国产欧美精品| 亚洲精品视频在线观看网站| 国产精品美女久久| 蜜桃av一区| 欧美四级电影网站| 羞羞色国产精品| 欧美国产成人在线| 久久米奇亚洲| 欧美三区不卡| 亚洲激情六月丁香| 激情小说另类小说亚洲欧美 | 欧美一区二区三区视频在线| 在线观看91精品国产入口| 亚洲欧美日韩一区二区| 一二三四社区欧美黄| 国产精品99久久久久久www| 国内外成人免费激情在线视频| 99riav1国产精品视频| 亚洲韩日在线| 久久五月天婷婷| 久久久久久亚洲精品中文字幕| 欧美日韩国产在线播放| 亚洲三级电影全部在线观看高清| 激情成人中文字幕| 欧美激情一区二区三区成人| 免费成人黄色片| 亚洲看片免费| 国产精品久久久久国产a级| 亚洲精品美女久久久久| 一本不卡影院| 国产精品美女主播| 午夜精品美女自拍福到在线 | 日韩视频免费| 欧美特黄一区| 久久国产精品黑丝| 91久久中文字幕| 久久精品国产久精国产思思| 亚洲电影在线观看| 欧美视频一区在线| 久久精品在线免费观看| 亚洲精品日韩在线| 免费在线看一区| 欧美日韩精品在线观看| 亚洲丰满在线| 国产精品99久久久久久久vr | 亚洲裸体视频| 欧美1区视频| 亚洲最黄网站| 亚洲二区精品| 久久久蜜桃精品| 欧美在线视频在线播放完整版免费观看| 国内在线观看一区二区三区| 亚洲免费高清| 欧美成人蜜桃| 美日韩精品免费| 久久午夜电影| 亚洲伊人久久综合| 欧美成人三级在线| 另类尿喷潮videofree| 午夜精品久久久久久久蜜桃app | 欧美国产日韩一区| 久久精品一区蜜桃臀影院| 亚洲一区二区三区国产| 最新成人av网站| 91久久精品国产91性色tv| 欧美色网一区二区| 韩日精品中文字幕| 欧美黄色免费| 国产日韩欧美视频在线| 久久香蕉精品| 欧美日韩免费在线| 欧美插天视频在线播放| 国产精品日韩专区| 亚洲日本va午夜在线电影| 国产在线一区二区三区四区| 亚洲精品乱码久久久久久| 亚洲高清视频在线观看| 欧美综合77777色婷婷| 午夜欧美精品久久久久久久| 欧美日韩国产页| 亚洲第一福利社区| 国产色婷婷国产综合在线理论片a| 欧美激情亚洲综合一区| 伊人色综合久久天天五月婷| 欧美一区2区视频在线观看 | 亚洲一区二区三区视频| 欧美黑人在线播放| 亚洲国产精品va在线观看黑人| 在线观看国产欧美| 久色成人在线| 亚洲国产成人porn| 一本到高清视频免费精品| 欧美日韩激情网| 在线视频一区二区| 欧美一级久久久久久久大片| 国产精品尤物| 久久精品国产欧美亚洲人人爽 | 99re66热这里只有精品3直播| 91久久精品国产91久久性色tv| 久久亚洲国产精品一区二区| 欧美成人精品在线播放| 亚洲国产欧美日韩| 欧美久久久久| 亚洲影院在线| 美女国产一区| 日韩一二三在线视频播| 国产精品成人久久久久| 午夜欧美大片免费观看| 蜜桃精品一区二区三区| 日韩香蕉视频| 国产区亚洲区欧美区| 久久午夜色播影院免费高清| 亚洲黄色一区| 欧美一区三区三区高中清蜜桃| 狠狠色综合网站久久久久久久| 模特精品在线| 亚洲一区国产视频| 蜜桃精品久久久久久久免费影院| 99精品久久| 国产一区二区日韩精品欧美精品| 美女国内精品自产拍在线播放| 99国产精品99久久久久久粉嫩| 久久se精品一区精品二区| 亚洲国产精品福利| 国产久一道中文一区| 欧美xart系列在线观看| 宅男噜噜噜66国产日韩在线观看| 国产精品免费看| 欧美3dxxxxhd| 香蕉成人伊视频在线观看| 亚洲国产mv| 久久理论片午夜琪琪电影网| 99精品欧美| 在线欧美日韩| 国产嫩草一区二区三区在线观看 | 9i看片成人免费高清| 国产三级精品三级| 欧美三级视频在线播放| 美女黄网久久| 久久国产一区| 亚洲综合电影一区二区三区| 91久久在线观看| 美女国产一区| 久久精品综合网| 性色av一区二区三区红粉影视| 亚洲片区在线| ●精品国产综合乱码久久久久| 国产区亚洲区欧美区| 国产精品久久激情| 欧美午夜精品久久久久久超碰| 欧美高清免费|