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

Shuffy

不斷的學習,不斷的思考,才能不斷的進步.Let's do better together!
posts - 102, comments - 43, trackbacks - 0, articles - 19
[轉(zhuǎn)]http://m.shnenglu.com/tiandejian/archive/2007/09/13/ec_27.html

第27條:     盡量不要使用類型轉(zhuǎn)換

C++ 的設(shè)計初衷之一就是:確保代碼遠離類型錯誤。從理論上來講,如果你的程序順利地通過了編譯,那么它就不會對任何對象嘗試去做任何不安全或無意義的操作。這是一項非常有價值的保證。你不應該輕易放棄它。

然而遺憾的是,轉(zhuǎn)型擾亂了原本井然有序的類型系統(tǒng)。它可以帶來無窮無盡的問題,一些是顯而易見的,但另一些則是極難察覺的。如果你是一名從 C Java 或者 C# 轉(zhuǎn)向 C++ 的程序員的話,那么請注意了,因為相對 C++ 而言,轉(zhuǎn)型在這些語言中更加重要,而且?guī)淼奈kU也小得多。但是 C++ 不是 C ,也不是 Java C# 。在 C++ 中,轉(zhuǎn)型是需要你格外注意的議題。

讓我們從復習轉(zhuǎn)型的語法開始,因為實現(xiàn)轉(zhuǎn)型有三種不同但是等價的方式。 C 風格的轉(zhuǎn)型是這樣的:

(T) 表達式                        // 表達式轉(zhuǎn)型為 T 類型的

函數(shù)風格的轉(zhuǎn)型如下:

T( 表達式 )                        // 表達式轉(zhuǎn)型為 T 類型的

兩者之間在含義上沒有任何的區(qū)別。這僅僅是你把括號放在哪兒的問題。我把這兩種形式稱為“懷舊風格的轉(zhuǎn)型”。

C++ 還提供了四種新的轉(zhuǎn)型的形式(通常稱為“現(xiàn)代風格”或“ C++ 風格”的轉(zhuǎn)型):

const_cast< T>( 表達式 )

dynamic_cast< T>( 表達式 )

reinterpret_cast< T>( 表達式 )

static_cast< T>( 表達式 )

四者各司其職:

const_cast 通常用來脫去對象的恒定性。 C++ 風格轉(zhuǎn)型中只有它能做到這一點。

dynamic_cast 主要用于進行“安全的向下轉(zhuǎn)型”,也就是說,它可以決定一個對象的類型是否屬于某一個特定的類型繼承層次結(jié)構(gòu)中。它是唯一一種懷舊風格語法所無法替代的轉(zhuǎn)型。它也是唯一一種可能會帶來顯著運行時開銷的轉(zhuǎn)型。(稍候會具體講解。)

reinterpret_cast 是為底層轉(zhuǎn)型而特別設(shè)置的,這類轉(zhuǎn)型可能會依賴于實現(xiàn)方式,比如說,將一個指針轉(zhuǎn)型為一個 int 值。除了底層代碼以外,要格外注意避免這類轉(zhuǎn)型。此類轉(zhuǎn)型在這本書中我只用過一次,而也是在討論如何編寫一個針對未分配內(nèi)存的調(diào)試分配器(參見第 50 條)用到。

static_cast 可以用于強制隱式轉(zhuǎn)換(比如說,將一個非 const 的對象轉(zhuǎn)換為 const 對象(就像第 3 條中的一樣), int 轉(zhuǎn)換為 double ,等等)。它可以用于大多數(shù)這類轉(zhuǎn)換的逆操作(比如說, void* 指針轉(zhuǎn)換為包含類型的指針,指向基類的指針轉(zhuǎn)換為指向繼承類的指針),但是它不能進行從 const 到非 const 對象的轉(zhuǎn)型。(只有 const_cast 可以。)

懷舊風格的轉(zhuǎn)型在 C++ 中仍然是合法的,但是這里更推薦使用新形式。首先,它們在代碼中更加易于辨認(不僅對人,而且對 grep 這樣的工具也是如此),對于那些類型系統(tǒng)亂成一團的代碼,這樣做可以減少我們?yōu)轭愋皖^疼的時間。其次,對每次轉(zhuǎn)型的目的更加細化,使得編譯器主動診斷用法錯誤成為可能。比如說,如果你嘗試通過轉(zhuǎn)型脫去恒定性的話,你只能使用 const_cast 如果你嘗試使用其它現(xiàn)代風格的轉(zhuǎn)型,你的代碼就不會通過編譯。

需要使用懷舊風格轉(zhuǎn)型的唯一一個地方就是:調(diào)用一 explicit 的構(gòu)造函數(shù)來為一個函數(shù)傳遞一個對象。比如:

class Widget {

public:

 explicit Widget(int size);

 ...

};

 

void doSomeWork(const Widget& w);

 

doSomeWork(Widget(15));               // 使用函數(shù)風格轉(zhuǎn)型

                                      // 創(chuàng)建一個 int Widget

 

doSomeWork(static_cast<Widget>(15)); // 使用 C++ 風格轉(zhuǎn)型

                                      // 創(chuàng)建一個 int Widget

出于某些原因,手動創(chuàng)建一個對象“感覺上”并不類似于一次轉(zhuǎn)型,所以在這種情況下應更趨向于使用函數(shù)風格的 轉(zhuǎn)型而不是 static_cast 。同時,當你寫下的代碼可能會導致 core dump[1] 時,你仍然會感覺你有充足的理由那樣做,因此你可能要忽略你的直覺,自始至終使用現(xiàn)代風格的轉(zhuǎn)型。

許多程序員相信轉(zhuǎn)型只是告訴編譯器將一個類型作為另一種來對待,僅此而已,但殊不知任何種類的類型轉(zhuǎn)換(無論是顯式的還是通過編譯器隱式進行的)通常會在運行時引入一些新的需要執(zhí)行的代碼。比如說,再下面的代碼片斷中:

int x, y;

...

double d = static_cast<double>(x)/y; // x 除以 y ,用浮點數(shù)保存商值

int x double 的轉(zhuǎn)型幾乎一定要引入新的代碼,因為在絕大多數(shù)架構(gòu)中, int double 的底層表示模式是不同的。這并不那么令人吃驚,但是下面的示例也許會讓你的眼界更加開闊些:

class Base { ... };

 

class Derived: public Base { ... };

 

Derived d;

 

Base *pb = &d;          // 隱式轉(zhuǎn)換: Derived* => base*

這里我們創(chuàng)建了一基類的指針,并讓其指向了一個派生類的對象,但是某些時候,這兩個指針值并不會保持一致。如果真的這樣了,系統(tǒng)會為 Derived* 指針應用一個偏移值來取得正確的 Base* 指針的值。

最近的一個實例顯示了一個單獨的對象(比如一個 Derived 的對象)可能會擁有一個以上的地址(比如,一個 Base* 指針指向它的地址和一個 Derived* 指針指向它的地址)。這件事在 C 語言中是絕不會發(fā)生的。同樣在 Java C# 中均不會發(fā)生。但在 C++ 中的的確確的發(fā)生了。實際上,在使用多重繼承時這件事是必然的,但在單繼承環(huán)境下也有可能發(fā)生。這意味著你應該避免去假設(shè)或推定 C++ 放置對象的方式,同時你應該避免基于這樣的假設(shè)來進行轉(zhuǎn)型。比如,如果你將對象地址轉(zhuǎn)型為 char* 指針,然后再對其進行指針運算,通常都會使程序陷入無法預知的行為。

但是請注意,我說過“某些時候”才需要引入偏移值。對象放置的方法、它們的地址的計算方法都是因編譯器而異的。這就意味著,僅僅由于你“知道對象如何放置”,你對在某一個平臺上轉(zhuǎn)型的做法可能充滿信心,但它在另一些平臺上卻是一錢不值。世界上有許多程序員為此付出了慘痛的代價。

關(guān)于轉(zhuǎn)型的一件有趣事情是:你很容易編寫一些 “看上去正確”的東西,但實際上它們是錯誤的。舉例說,許多應用程序框架需要在派生類中實現(xiàn)一個虛擬成員函數(shù),并首先讓這些函數(shù)去調(diào)用基類中對應的函數(shù)。假設(shè)我們有一個 Window 基類和一個 SpecialWindow 派生類,兩者都定義了虛函數(shù) onResize 。繼續(xù)假設(shè): SpecialWindow onResize 首先會調(diào)用 Window onResize 。以下是實現(xiàn)方法,它乍看上去是正確的,其實不然:

class Window {                        // 基類

public:

 virtual void onResize() { ... }     // 基類 onResize 的實現(xiàn)

 ...

};

 

 

 

class SpecialWindow: public Window { // 派生類

public:

 virtual void onResize() {                // 派生類 onResize 的實現(xiàn)

    static_cast<Window>(*this).onResize(); // *this 轉(zhuǎn)型為 Window

                                           // 然后調(diào)用它的 onResize

                                           // 這樣不會正常工作!

    ...                           // 完成 SpecialWindow 獨有的任務(wù)

 }

 ...

};

上面代碼中的轉(zhuǎn)型操作已經(jīng)用黑體字標出。(這是一個現(xiàn)代風格的轉(zhuǎn)型,但是如果使用懷舊風格的話也不會帶來任何影響。)如果一切如你所愿,代碼將會 *this 轉(zhuǎn)型為一個 Window ,同時此過程帶來一次 onResize 的調(diào)用,將會是 Window::onResize 。你一定沒有想到,當前對象并沒有調(diào)用這一函數(shù)。取而代之的是,轉(zhuǎn)型過程創(chuàng)建了一個新的, *this 中基類部分的一個臨時副本,然后調(diào)用這一副本的 onResize 。上面的代碼將不會調(diào)用當前對象的 Window::onResize ,然后進行對象中的具體到 SpecialWindow 的動作;而是再對當前對象進行 SpecialWindow 行為之前,去調(diào)用當前對象的基類部分的副本中的 Window::onResize 。如果 Window::onResize 希望修改當前對象(這也不是完全不可行,因為 onResize 是一個非 const 的成員函數(shù)),實際上當前對象不會受到任何影響。取而代之的是,這一對象的那個副本將會被修改。然而,如果 SpecialWindow::onResize 希望修改當前對象,當前對象將會被修改,這將導致下面的情景:代碼將會使當前對象處于病態(tài)之中——它基類部分的修改沒有進行,而派生類部分的修改卻完成了。

解決方案就是:避免轉(zhuǎn)型。轉(zhuǎn)而使用你真正需要的類型。你并不希望欺騙編譯器將一個 *this 識別為一個基類對象;你需要做的是:對當前對象調(diào)用 onResize 的基類版本。所以你應該這樣編寫:

class SpecialWindow: public Window {

public:

 virtual void onResize() {

    Window::onResize();          // *this 調(diào)用 Window::onResize

    ...

 }

 ...

 

};

這個示例同時告訴我們:如果你需要進行轉(zhuǎn)型,上面的代碼就會發(fā)出警告:你可能正在以錯誤的方式工作。尤其是 dynamic_cast

在深入探究 dynamic_cast 的實現(xiàn)設(shè)計方式之前,有必要先了解一下大多數(shù) dynamic_cast 的實現(xiàn)運行的速度是非常緩慢的。比如說,至少有一種通用實現(xiàn)是通過比較各個類名的字符串。如果你正在針對一個四層深的單一繼承層次結(jié)構(gòu)中的一個對象進行 dynamic_cast ,那么這種實現(xiàn)方式下,每一次 dynamic_cast 都會占用四次調(diào)用 strcmp 的時間用于比較類名。顯然地,更深的或者使用多重繼承的層次結(jié)構(gòu)的開銷將會更為顯著。一些實現(xiàn)以這種方式運行也是有它的根據(jù)的(它們這樣做是為了支持動態(tài)鏈接)。在對性能要求較高的代碼中,要在整體上時刻對轉(zhuǎn)型持謹慎的態(tài)度,你應該特別謹慎地使用 dynamic_cast

一般說來,在你期望對那些你確認屬于派生類的對象進行派生類操作,但此時你只有一個指針或者一個指向基類的引用能操作這一對象, dynamic_cast 將派上用場。一般有兩條途徑來避免這一問題。

首先,可以使用容器來保存直接指向派生類對象的指針(通常是指能指針,參見第 13 條),這樣就在對這些對象進行操作時就無需通過基類接口。比如說,在我們的 Window/SpecialWindow 層次結(jié)構(gòu)中,如果只有 SpecialWindow 支持閃爍效果,我們也許可以這樣做:

class Window { ... };

 

class SpecialWindow: public Window {

public:

 void blink();

 ...

};

 

typedef std::vector<std::tr1::shared_ptr<Window> > VPW;

// 關(guān)于 tr1::shared_ptr 的信息請參見第 13

 

VPW winPtrs;

 

...

 

for (VPW::iterator iter = winPtrs.begin();   // 不好的代碼。

     iter != winPtrs.end();                  // 使用 dynamic_cast

     ++iter) {

 if (SpecialWindow *psw = dynamic_cast<SpecialWindow*>(iter->get()))

     psw->blink();

}

但是有更好的解決方案:

typedef std::vector<std::tr1::shared_ptr<SpecialWindow> > VPSW;

 

VPSW winPtrs;

 

...

 

for (VPSW::iterator iter = winPtrs.begin();// 更好的代碼

     iter != winPtrs.end();                 // 無需 dynamic_cast

     ++iter)

 (*iter)->blink();

當然,在使用這一方案時,在同一容器中放置 Window 派生對象的類型是受到限制的。為了使用更多的 Window 類型,你可能需要多個類型安全的容器。

一個可行的替代方案是:在基類中提供虛函數(shù),然后按需配置。這樣對于所有可能的 Window 派生類型,你都可以通過基類接口來進行操作了。比如說,盡管只有 SpecialWindow 可以閃爍,但是在基類中聲明這一函數(shù)也是有意義的,可以提供一個默認的實現(xiàn),但不去做任何事情:

class Window {

public:

 virtual void blink() {}        // 默認實現(xiàn)不做任何事情;

 ...                            // 34 條將介紹:

};                              // 提供默認實現(xiàn)可能是個壞主意

 

class SpecialWindow: public Window {

public:

 virtual void blink() { ... }; // 在這一類型中

 ...                            // blink 函數(shù)會做一些事情

};

 

typedef std::vector<std::tr1::shared_ptr<Window> > VPW;

 

VPW winPtrs;                     // 容器中保存著(指向)

...                             // 所有可能的 Window 類型

 

for (VPW::iterator iter = winPtrs.begin(); iter != winPtrs.end(); ++iter)

                                // 請注意這里沒有 dynamic_cast

 (*iter)->blink();

上面的這兩種實現(xiàn)(使用類型安全的容器,或者在層次結(jié)構(gòu)的頂端添加虛函數(shù))都不是萬能的。但在大多數(shù)情況下,它們是 dynamic_cast 良好的替代方案。如果你發(fā)現(xiàn)其中一種方案可行,大可以欣然接受。

關(guān)于 dynamic_cast 有一件事情自始至終都要注意,那就是:避免級聯(lián)使用。就是說要避免類似下面的代碼出現(xiàn):

class Window { ... };

 

...                             // 此處定義派生類

 

typedef std::vector<std::tr1::shared_ptr<Window> > VPW;

 

VPW winPtrs;

 

...

 

for (VPW::iterator iter = winPtrs.begin(); iter != winPtrs.end(); ++iter)

{

 if (SpecialWindow1 *psw1 =

       dynamic_cast<SpecialWindow1*>(iter->get())) { ... }

 

 else if (SpecialWindow2 *psw2 =

            dynamic_cast<SpecialWindow2*>(iter->get())) { ... }

 

 else if (SpecialWindow3 *psw3 =

            dynamic_cast<SpecialWindow3*>(iter->get())) { ... }

 

 ...

}

這樣的代碼經(jīng)編譯后得到的可執(zhí)行代碼將是冗長而性能低下的,并且十分脆弱,這是因為每當 Window 的類層次結(jié)構(gòu)有所改變時,就需要檢查所有這樣的代碼,以斷定它們是否需要更新。(比如說,如果添加了一個新的派生類,上面的級聯(lián)操作中就需要添加一個新的條件判斷分支。)這樣的代碼還是由虛函數(shù)調(diào)用的方式取代為好。

優(yōu)秀的 C++ 代碼中使用轉(zhuǎn)型應該是十分謹慎的,但是一般說來并不是要全盤否定。比如說,本書 118 [2] 中從 int double 的轉(zhuǎn)型,就是一次合理而有用的轉(zhuǎn)型,盡管它并不是必需的。(代碼可以這樣重寫:生命一個新的 double 類型的變量,并且用 x 的值對其進行初始化。)和其他絕大多數(shù)可以結(jié)構(gòu)一樣,轉(zhuǎn)型應該盡可能的與其它代碼隔離,典型的方法是將其隱藏在函數(shù)中,這些函數(shù)的的接口就可以防止調(diào)用者接觸其內(nèi)部復雜的操作。

銘記在心

盡可能避免使用轉(zhuǎn)型,尤其是在對性能敏感的代碼中不要使用動態(tài)轉(zhuǎn)型 dynamic_cast 。如果一個設(shè)計方案需要使用轉(zhuǎn)型,要嘗試尋求一條不需要轉(zhuǎn)型的方案來取代。

在必須使用轉(zhuǎn)型時,要嘗試將其隱藏在一個函數(shù)中。這樣客戶端程序員就可以調(diào)用這些函數(shù),而不是在他們自己的代碼中使用轉(zhuǎn)型。

要盡量使用 C++ 風格的轉(zhuǎn)型,避免使用懷舊風格的轉(zhuǎn)型。現(xiàn)代的轉(zhuǎn)型更易讀,而且功能更為具體化。



[1] 在編寫一個程序時,出于種種原因經(jīng)常會自動關(guān)閉或出錯。雖然操作系統(tǒng)沒出問題,但考慮到下次仍可能遇到相同的問題,操作系統(tǒng)就會把程序出錯時的內(nèi)存( core )中的內(nèi)容轉(zhuǎn)移( dump )出來供調(diào)試人員參考。此為 core dump 。——譯注。

 

[2] 前文中的 doSomeWork(Widget(15)) 使用函數(shù)風格轉(zhuǎn)型創(chuàng)建一個 int Widget —— 譯注

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            亚洲精品在线视频| 欧美激情1区2区| 国模精品一区二区三区| 国产精品theporn| 欧美激情在线| 欧美日韩亚洲一区二区三区在线| 欧美日韩1234| 欧美日韩国产在线一区| 欧美日韩在线观看一区二区三区 | 99国产精品| 一本色道久久88亚洲综合88| 亚洲精品综合精品自拍| 亚洲精品影院| 亚洲一区二区三区精品动漫| 欧美一区影院| 欧美成年人在线观看| 欧美精品国产一区| 亚洲自啪免费| 老司机久久99久久精品播放免费| 久久久五月婷婷| 欧美精品18+| 亚洲欧洲综合| 亚洲国产另类 国产精品国产免费| 欧美bbbxxxxx| 91久久久在线| 一区二区三区色| 久久久91精品| 国产精品久久久久aaaa| 激情久久久久久久| 亚洲视频免费观看| 久久久国产一区二区| 亚洲国产精品一区二区第一页 | 亚洲精品久久久久久久久久久久久 | 日韩天堂在线观看| 新片速递亚洲合集欧美合集| 欧美在线视频全部完| 欧美a级片网站| 99在线精品视频| 久久精品视频免费播放| 欧美亚一区二区| 国产亚洲人成网站在线观看| 一区二区av| 久久永久免费| 国产精品99久久久久久白浆小说| 久久字幕精品一区| 国产乱码精品一区二区三区五月婷 | 宅男精品视频| 亚洲一区一卡| 欧美紧缚bdsm在线视频| 国内揄拍国内精品少妇国语| 亚洲精品在线三区| 狼人社综合社区| 午夜久久美女| 国产精品一区二区久激情瑜伽| 亚洲图片激情小说| 亚洲精品乱码久久久久久蜜桃麻豆 | 国产精品免费观看视频| 欧美成人激情在线| 久久这里只有| 在线观看三级视频欧美| 久久先锋资源| 久久久91精品国产| 一区二区三区在线不卡| 久久久亚洲精品一区二区三区 | 亚洲一卡二卡三卡四卡五卡| 国产精品jizz在线观看美国| 一本大道久久精品懂色aⅴ| 亚洲欧洲在线看| 欧美日本在线视频| 亚洲午夜久久久| 亚洲一区二区高清| 国产美女精品在线| 久久综合九色99| 久久一区二区三区av| 一色屋精品亚洲香蕉网站| 欧美大片免费| 欧美精品18+| 亚洲精品久久| 亚洲一区免费在线观看| 国产综合视频| 久久蜜桃资源一区二区老牛| 欧美a级片网站| 99精品国产一区二区青青牛奶| 亚洲国产片色| 国产精品成人一区二区艾草| 亚洲欧美日韩国产一区| 欧美一区三区二区在线观看| 国产欧美日韩亚洲精品| 老**午夜毛片一区二区三区| 欧美成人国产一区二区| 在线亚洲美日韩| 中文亚洲视频在线| 精品91免费| 中日韩男男gay无套 | 亚洲欧洲精品一区二区精品久久久 | 亚洲福利国产精品| 欧美日韩在线播放三区| 嫩草影视亚洲| 亚洲国产免费看| 国产精品视频yy9099| 久久精品主播| 欧美伦理91| 久久精品综合网| 欧美日韩另类视频| 久久一日本道色综合久久| 麻豆亚洲精品| 午夜精品久久久久久久99樱桃| 欧美专区福利在线| 国产精品99久久久久久www| 亚洲欧美999| 99在线精品视频| 欧美综合国产| 一本色道久久88综合日韩精品 | 精品不卡一区| 一区二区三区欧美成人| 狠狠色香婷婷久久亚洲精品| 亚洲国产视频直播| 国产日韩欧美一区二区| 在线视频你懂得一区二区三区| 亚洲精品视频在线观看免费| 久久精品一二三| 久久精品中文字幕一区| 国产精品国产三级国产aⅴ9色| 亚洲福利视频在线| 在线日韩av| 久久国产夜色精品鲁鲁99| 亚洲欧美另类国产| 欧美午夜精品久久久| 亚洲精品在线二区| 亚洲巨乳在线| 欧美精品www在线观看| 最新日韩av| 亚洲无毛电影| 国产精品久久999| 一区二区三区久久久| 亚洲在线日韩| 国产精品每日更新在线播放网址| 9人人澡人人爽人人精品| 日韩一区二区精品| 欧美日韩国产在线观看| 欧美成人中文字幕| 亚洲午夜在线观看| 亚洲网址在线| 国产精品羞羞答答xxdd| 亚洲无线观看| 亚洲欧美日韩成人| 国产精品日韩电影| 午夜精品影院在线观看| 欧美伊久线香蕉线新在线| 国产精品进线69影院| 国产精品99久久久久久www| 欧美大片专区| 亚洲精品中文字| 亚洲自拍偷拍网址| 国产情人综合久久777777| 欧美一级午夜免费电影| 久久久人成影片一区二区三区 | 亚洲欧美日本国产专区一区| 亚洲女女做受ⅹxx高潮| 国产精品久久久久久久久久免费| 亚洲视频一区二区免费在线观看| 亚洲女爱视频在线| 国户精品久久久久久久久久久不卡| 久久久亚洲国产美女国产盗摄| 亚洲二区视频在线| 欧美一区二区三区精品| 亚洲国产欧美日韩另类综合| 欧美色播在线播放| 欧美在线国产精品| 亚洲黄色在线看| 亚洲欧美日韩一区二区三区在线观看| 国产视频一区在线| 欧美成人一区二免费视频软件| 亚洲精品综合久久中文字幕| 欧美亚洲日本一区| 亚洲激情在线| 国产嫩草一区二区三区在线观看| 久久综合激情| 欧美片第1页综合| 欧美激情女人20p| 亚洲欧美日韩视频二区| 亚洲精品黄色| 狠狠色狠狠色综合日日小说| 欧美日本在线看| 久久久国产精彩视频美女艺术照福利| 亚洲三级性片| 欧美69wwwcom| 久久激情视频| 亚洲天堂av在线免费观看| 精品成人一区二区| 国产精品午夜av在线| 欧美日韩综合一区| 麻豆国产精品777777在线| 午夜亚洲视频| 亚洲少妇诱惑| 99国产精品久久久久久久| 欧美国产精品专区| 美女精品自拍一二三四| 久久国产夜色精品鲁鲁99| 亚洲影院在线|