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

Shuffy

不斷的學(xué)習(xí),不斷的思考,才能不斷的進(jìn)步.Let's do better together!
posts - 102, comments - 43, trackbacks - 0, articles - 19
[轉(zhuǎn)]http://m.shnenglu.com/tiandejian/archive/2007/10/04/ec_29.html

第29條:     力求使代碼做到“異常安全”

異常安全看上去像是孕育生命,但是請(qǐng)您先把這種觀點(diǎn)暫時(shí)放在腦后。因?yàn)樵谝粚?duì)戀人結(jié)婚之前,討論生育問題還為時(shí)尚早。

假設(shè)我們正在設(shè)計(jì)一個(gè)表示 GUI 菜單的類,這種菜單是有背景圖片的,這個(gè)類用于多線程環(huán)境中,所以它擁有一個(gè)互斥鎖來(lái)確保正常的并發(fā)控制:

class PrettyMenu {

public:

 ...

 void changeBackground(std::istream& imgSrc); // 更改背景圖片

   ...

 

private:

 Mutex mutex;                   // 本對(duì)象使用的互斥鎖

 

 Image *bgImage;                // 當(dāng)前的背景圖片

 int imageChanges;              // 圖片更改的次數(shù)

};

下面是 PrettyMenu changeBackground 函數(shù)實(shí)現(xiàn)的一個(gè)備選方案:

void PrettyMenu::changeBackground(std::istream& imgSrc)

{

 lock(&mutex);                  // 請(qǐng)求上鎖 ( 同第 14 )

 

 delete bgImage;                // 刪除舊的背景圖片

 ++imageChanges;                // 更新圖片改變的次數(shù)

 bgImage = new Image(imgSrc);   // 裝載新的背景圖片

 

 unlock(&mutex);                // 解鎖

}

從異常安全的角度來(lái)說(shuō),這個(gè)函數(shù)簡(jiǎn)直一無(wú)是處。異常安全的兩個(gè)基本要求,這個(gè)函數(shù)完全沒有考慮到。

當(dāng)拋出異常時(shí),異常安全的代碼應(yīng)該做到:

要泄漏資源。 上面的代碼沒有進(jìn)行這項(xiàng)檢測(cè),這是因?yàn)槿绻?/span> new Image(imgSrc) 語(yǔ)句產(chǎn)生了異常 ,那么對(duì) unlock 的調(diào)用則永遠(yuǎn)不會(huì)兌現(xiàn),這樣互斥鎖將永遠(yuǎn)不會(huì)被解開。

不能讓數(shù)據(jù)結(jié)構(gòu)遭到破壞。 如果“ new Image(imgSrc) ”拋出異常, bgImage 就會(huì)指向一個(gè)已經(jīng)銷毀的對(duì)象。另外,無(wú)論新的圖形是否裝載成功, imageChanges 的數(shù)值都會(huì)增加。(從另一個(gè)角度說(shuō),舊的圖形肯定是被刪除了,那么你又怎么能確保圖形被“改變”了呢。)

處理資源泄漏問題還是比較簡(jiǎn)單的,因?yàn)榈?/span> 13 條中介紹過如何使用對(duì)象來(lái)管理資源,第 14 條中介紹過如何通過 Lock 類確?;コ怄i在適當(dāng)?shù)臅r(shí)候被解開:

void PrettyMenu::changeBackground(std::istream& imgSrc)

{

 Lock ml(&mutex);               // 來(lái)自第 14 條的經(jīng)驗(yàn):

                                // 申請(qǐng)一個(gè)互斥鎖,并適時(shí)解鎖

 delete bgImage;

 ++imageChanges;

 bgImage = new Image(imgSrc);

}

能夠讓函數(shù)變得更短,是諸如 Lock 這樣的資源管理類最讓人興奮的事情之一。你是否注意到:這里甚至不需要調(diào)用 unlock 。更短的代碼就是更優(yōu)秀的代碼,因?yàn)榇a越短,它帶來(lái)錯(cuò)誤和誤解的機(jī)會(huì)就越少。這是一條通用的準(zhǔn)則。

把資源泄漏問題放在一旁,讓我們把注意力集中在數(shù)據(jù)結(jié)構(gòu)破壞的問題上。這里我們可以進(jìn)行一次選擇,但是在進(jìn)行選擇之前,我們首先要了解所需要的幾個(gè)術(shù)語(yǔ)。

異常安全函數(shù)做出的保證可以總結(jié)為三個(gè)層面:

提供基本保證的函數(shù)會(huì)做出這樣的承諾:如果拋出了一個(gè)異常,那么程序中的一切都將保持合法的狀態(tài)。沒有任何對(duì)象或數(shù)據(jù)結(jié)構(gòu)會(huì)遭到破壞,所有的對(duì)象的內(nèi)部都保持協(xié)調(diào)的狀態(tài)(比如說(shuō)所有類不變式都得到滿足)。然而,程序的具體狀態(tài)可能是無(wú)法預(yù)知的。比如說(shuō),我們可以這樣編 changeBackground :如果某一時(shí)刻拋出一個(gè)異常,那么 PrettyMenu 對(duì)象可能繼續(xù)使用舊的背景圖片,也可以用某個(gè)默認(rèn)的背景圖片來(lái)代替。但是客戶端程序員無(wú)法做出任何預(yù)測(cè)。(為了找到答案,客戶端程序員大概會(huì)調(diào)用某個(gè)能告訴他們當(dāng)前背景圖片是什么的成員函數(shù)。)

提供增強(qiáng)保證的函數(shù)會(huì)做出這樣的承諾:如果拋出了一個(gè)異常,那么函數(shù)的狀態(tài)將保持不變。這樣的函數(shù)看上去與原子有些相像,因?yàn)槿绻{(diào)用成功了,它就會(huì)大獲全勝;一旦出了差錯(cuò),那么就會(huì)一敗涂地,程序狀態(tài)將顯示它從來(lái)沒有被調(diào)用過。

使用提供強(qiáng)保證的的函數(shù)要比使用僅提供基本保證的函數(shù)簡(jiǎn)單一些,這是因?yàn)樵谡{(diào)用一個(gè)提供強(qiáng)保證的函數(shù)之后,程序只可能存在兩種狀態(tài):一、按預(yù)期進(jìn)行,函數(shù)成功執(zhí)行;二、程序?qū)⒈3趾瘮?shù)調(diào)用前的狀態(tài)。反觀提供基本保證的函數(shù),如果在調(diào)用它時(shí)拋出了一個(gè)異常,那么程序可能會(huì)處于任何合法的狀態(tài)。

提供零異常保證的函數(shù)承諾程序決不會(huì)拋出異常,因?yàn)樗鼈冇肋h(yuǎn)都會(huì)按部就班的運(yùn)行。所有的內(nèi)建數(shù)據(jù)類型 int 、指針,等等)的操作都是零異常的(提供零異常保證)。這是異常安全代碼必不可少的一個(gè)因素。

我們可以假設(shè)包含空異常規(guī)范 [1] 的函數(shù)為零異常的,這樣做看上去是合理的,但是事實(shí)并不一定是這樣的,請(qǐng)看下面的函數(shù):

int doSomething() throw();          // 記錄空異常規(guī)范

這并不是說(shuō) doSomething 將永遠(yuǎn)不會(huì)拋出異常,這只是說(shuō),如果 doSomething 拋出了異常,那么此時(shí)就出現(xiàn)了一個(gè)嚴(yán)重的錯(cuò)誤,同時(shí)程序應(yīng)該調(diào)用一個(gè)名為 unexpected 的函數(shù) [2] 。實(shí)際上, doSomething 可能根本不會(huì)提供任何異常保證。函數(shù)的聲明(包括它的異常規(guī)范,如果有的話)并不會(huì)告訴你它是否正確、是否小巧、是否高效,同時(shí)也不會(huì)告訴你它他提供了哪個(gè)層面上的異常安全保證。所有那些特性都要在函數(shù)實(shí)現(xiàn)中確定下來(lái),而不是聲明中。

異常安全的代碼必須要提供上述三個(gè)層面的保證中的一種。否則它就不是異常安全的。那么你要做的就是:對(duì)于所寫的每一個(gè)函數(shù)都要確定使用哪一層面保證。除非我們正在處理沒有做到異常安全的糟糕代碼(這一點(diǎn)我們稍候再提)。只有當(dāng)你的“優(yōu)秀”的需求分析小組提出:你的程序需要泄露資源,并且需要使用破壞的數(shù)據(jù)結(jié)構(gòu)時(shí),不提供任何異常安全保證也許才是一個(gè)可行的選擇。

作為一個(gè)通用的準(zhǔn)則,你會(huì)希望提供可行范圍內(nèi)最強(qiáng)化的保證。從異常安全的角度來(lái)說(shuō),零異常的函數(shù)是美妙的,但是如果不去調(diào)用拋出異常的函數(shù),你是很難逾越 C++ C 這一部分的。只要涉及動(dòng)態(tài)內(nèi)存分配(比如所有的 STL 容器),如果無(wú)法尋找到足夠的內(nèi)存來(lái)滿足當(dāng)前的要求,那么通常程序都會(huì)拋出一 個(gè) bad_alloc 異常(參見第 49 條)。在可行的時(shí)候你應(yīng)該為函數(shù)提供零異常保證,但是對(duì)于大多數(shù)函數(shù)而言,懸在是介于基本保證和增強(qiáng)保證之間的。

對(duì)于 changeBackground 而言,或多或少地提供增強(qiáng)保證并不是件難事。首先,我們可以改變 PrettyMenu bgImage 數(shù)據(jù)成員的類型,從一個(gè)內(nèi)建的 Image* 指針類型轉(zhuǎn)變?yōu)橹悄苜Y源管理指針(參見第 13 條)。坦白的說(shuō),單獨(dú)從防止資源泄漏理論的角度上說(shuō),這是一個(gè)非常好的設(shè)計(jì)方案。事實(shí)上它簡(jiǎn)單地通過使用對(duì)象(比如智能指針)來(lái)管理資源(也就是遵循了 13 條中的建議,這是優(yōu)秀設(shè)計(jì)的基本要求),幫助我們提供了增強(qiáng)的異常安全保證。在下面的代碼中,我將使用 tr1::shared_ptr ,這是因?yàn)樗男袨楦庇^,在進(jìn)行復(fù)制操作時(shí)比 auto_ptr 更合適。

其次,我們從新編排了 changeBackground 中語(yǔ)句的順序,從而使 imageChanges 直到圖像改變以后才進(jìn)行自加。作為一個(gè)通用的準(zhǔn)則,直到一個(gè)事件真真切切地發(fā)生了,才去改變對(duì)象的狀態(tài)來(lái)描述這個(gè)事件。

下面是改進(jìn)后的代碼:

class PrettyMenu {

 ...

 std::tr1::shared_ptr<Image> bgImage;

 ...

};

 

void PrettyMenu::changeBackground(std::istream& imgSrc)

{

 Lock ml(&mutex);

 

 bgImage.reset(new Image(imgSrc));   // bgImage 的內(nèi)部指針替換為

                                      //”new Image” 表達(dá)式的結(jié)果

 ++imageChanges;

}

請(qǐng)注意這里不需要手動(dòng)刪除舊圖片,因?yàn)檫@件事情完全由智能指針代勞了。而且,只有在新圖像成功創(chuàng)建之后,刪除操作才有意義。更精確地說(shuō), tr1::shared_ptr::reset 函數(shù)只有在其參數(shù)( ”new Image(imgSrc)” 的結(jié)果)成功創(chuàng)建以后才會(huì)得到調(diào)用。由于只有在調(diào)用 reset 過程中才會(huì)使用 delete ,因此如果從未進(jìn)入該函數(shù),就永遠(yuǎn)不會(huì)用到 delete 。注意:使用對(duì)象( tr1::shared_ptr )來(lái)管理資源(動(dòng)態(tài)分配的 Image ),再次精簡(jiǎn)了 changeBackground 。

如前所述,這兩項(xiàng)改變或多或少地使 changeBackground 滿足了增強(qiáng)的異常安全保證??墒?/span> 白璧微瑕, imgSrc 參數(shù) 還有 一個(gè)小問題。 如果 Image 的構(gòu)造函數(shù)拋出了一個(gè)異常,那么輸入流的讀標(biāo)記很可能會(huì)被移動(dòng),這樣的移動(dòng)可能會(huì)造成狀態(tài)的變化,而這種變化對(duì)程序其它部分來(lái)說(shuō)是可見的。在 changeBackground 指明這一問題之前,它僅僅提供基本的異常安全保證。

然而,讓我們把這個(gè)問題暫時(shí)放在一旁,假裝 changeBackground 確實(shí)可以提供增強(qiáng)保證。(我相信你可以想出一個(gè)辦法來(lái),可以通過改變參數(shù)的類型:從輸入流變?yōu)榘瑘D像信息的文件名。)有一個(gè)一般化的設(shè)計(jì)方案,可以使函數(shù)做到增強(qiáng)保證,了解這種放案十分重要。這一方案一般稱為“復(fù)制并交換。”從理論上來(lái)講,它非常簡(jiǎn)單。為需要修改的對(duì)象做一個(gè)副本,然后將所有需要的改變應(yīng)用于這個(gè)副本之上。如果期間任一個(gè)修改操作拋出了異常,那么原始的對(duì)象依然紋絲未動(dòng)。在所有改變順利完成之后,通過一次不拋出異常的操作將修改過的對(duì)象與原始對(duì)象相交換即可。

上述方案通常這樣實(shí)現(xiàn):將對(duì)象的所有數(shù)據(jù)從“真實(shí)的”對(duì)象復(fù)制到一個(gè)獨(dú)立實(shí)現(xiàn)的對(duì)象中,然后為真實(shí)對(duì)象創(chuàng)建一個(gè)指針,將其指向這個(gè)實(shí)現(xiàn)對(duì)象。這通常稱為“ pimpl idiom ”(指向?qū)崿F(xiàn)的指針),第 31 條中將將解它的一些細(xì)節(jié)。對(duì)于 PrettyMenu 而言,典型的實(shí)現(xiàn)是這樣的:

struct PMImpl {                 // PMImpl = PrettyMenu 的實(shí)現(xiàn)

 std::tr1::shared_ptr<Image> bgImage;

 int imageChanges;              // 下文將介紹它為什么是結(jié)構(gòu)體

};

 

class PrettyMenu {

 ...

 

private:

 Mutex mutex;

 std::tr1::shared_ptr<PMImpl> pImpl;

};

 

void PrettyMenu::changeBackground(std::istream& imgSrc)

{

 using std::swap;               // 參見第 25

 

 Lock ml(&mutex);               // 上鎖

 

 std::tr1::shared_ptr<PMImpl>   // 復(fù)制 對(duì)象數(shù)據(jù)

    pNew(new PMImpl(*pImpl));

 

 pNew->bgImage.reset(new Image(imgSrc));   // 修改副本

 ++pNew->imageChanges;

 

 swap(pImpl, pNew);             // 交換 新數(shù)據(jù)就位

 

}                               // 解鎖

在這個(gè)示例中,我做出了這樣的選擇: PMImpl 是一個(gè)結(jié)構(gòu)體而不是類,這是因?yàn)?/span> PrettyMenu 數(shù)據(jù)的封裝性是通過 pImpl 確定為私有的。將 PMImpl 實(shí)現(xiàn)為類不但不會(huì)帶來(lái)便利,而且效果也不好。(它同樣使面向?qū)ο蟮钠珗?zhí)狂陷入絕境。)如果需要,可以把 PMImpl 放置在 PrettyMenu 的內(nèi)部,但是打包問題與編寫異常安全代碼的問題似乎沒有什么聯(lián)系,這不是我們當(dāng)前所關(guān)注的。

有些對(duì)象狀態(tài)修改的操作,要求要么是完全修改,要么完全不變,此時(shí)復(fù)制并交換策略是完美的。但是,一般情況下,它并不能確保整個(gè)函數(shù)都做到增強(qiáng)保證。請(qǐng)看下面 changeBackground 的一個(gè)抽象—— someFunc ,它使用了復(fù)制并交換策略,但是它包含了 2 個(gè)其它函數(shù)的調(diào)用:

void someFunc()

{

 ...                            // 為本地的狀態(tài)創(chuàng)建副本

 f1();

 f2();

 ...                            // 交換修改后的狀態(tài)就位

}

這里應(yīng)該很清楚了:如 f1 或者 f2 沒有達(dá)到增強(qiáng)保證的要求,那么 someFunc 就很難滿足增強(qiáng)保證。比如,假設(shè) f1 僅提供了基本保證,為了讓 someFunc 能滿足增強(qiáng)保證,就必須要為其編寫額外的代碼,用于調(diào)用 f1 之前確定整個(gè)程序的狀態(tài),捕獲 f1 拋出的所有異常,然后恢復(fù)原始的狀態(tài)。

如果 f1 f2 都滿足了增強(qiáng)保證,那么事情也不會(huì)好到哪去。如果 f1 運(yùn)行完成,那么程序的狀態(tài)可能經(jīng)歷了任意的修改過程,因此,如果 f2 在此時(shí)拋出了一個(gè)異常,那么程序的狀態(tài)就可能會(huì)與 someFunc 被調(diào)用時(shí)不一致,即使 f2 沒有做任何修改操作。

這個(gè)問題是個(gè)側(cè)面效應(yīng)。只要函數(shù)操作僅僅針對(duì)本地的狀態(tài)(比如說(shuō), someFunc 僅僅影響到它所調(diào)用對(duì)象的狀態(tài)),提供增強(qiáng)保證就相對(duì)簡(jiǎn)單些。當(dāng)函數(shù)對(duì)于非本地?cái)?shù)據(jù)存在這一側(cè)面效應(yīng)時(shí),則更加困難些。比如說(shuō),如果調(diào)用 f1 引入的側(cè)面效應(yīng)是數(shù)據(jù)庫(kù)被修改了,那么讓 someFunc 滿足異常安全的增強(qiáng)保證就比較困難。一般來(lái)說(shuō),已經(jīng)被系統(tǒng)接受的數(shù)據(jù)庫(kù)修改很難恢復(fù),這是因?yàn)槠渌臄?shù)據(jù)庫(kù)用戶已經(jīng)看到了數(shù)據(jù)庫(kù)的新狀態(tài)。

不管你情愿與否,諸如這樣的問題會(huì)為你在編寫增強(qiáng)保證的函數(shù)時(shí)設(shè)置重重障礙。另一個(gè)問題是:效率。復(fù)制并交換策略的核心思想就是修改對(duì)象副本的數(shù)據(jù),然后通過一個(gè)不會(huì)拋出異常地操作交換修改后的數(shù)據(jù)。這需要為每個(gè)需要修改的對(duì)象創(chuàng)建出一個(gè)副本,這樣做顯然會(huì)浪費(fèi)時(shí)間和空間,你也許不會(huì)情愿使用這一策略,現(xiàn)實(shí)條件有時(shí)也會(huì)阻止你。增強(qiáng)保證是我們良好的預(yù)期目標(biāo),只要可行你就應(yīng)該提供,但是現(xiàn)實(shí)中它并不總是可行的。

在增強(qiáng)保證不可行時(shí),你應(yīng)該提供基本保證。從實(shí)用角度說(shuō),如果你發(fā)現(xiàn)你可以為某些函數(shù)提供增強(qiáng)保證,但是由此帶來(lái)的效率和復(fù)雜度問題使得增強(qiáng)保證變得得不償失。只要你在必要的時(shí)候做出了努力使適當(dāng)?shù)暮瘮?shù)滿足了增強(qiáng)保證,那么對(duì)于一些函數(shù)僅提供基本保證就是無(wú)可厚非的。對(duì)于大多數(shù)函數(shù)而言,基本保證已經(jīng)是合理的、完美的選擇了。

如果你正在編寫一個(gè)完全不提供異常安全保證的函數(shù),那么就是另一番景象了。因?yàn)樵谶@里完全可以在未證明你無(wú)罪之前假定你有罪。你本應(yīng)該編寫異常安全代碼。但是你也可以為自己做出強(qiáng)有力的辯解。請(qǐng)?jiān)俅慰紤]一下 someFunc 的實(shí)現(xiàn),它調(diào)用了兩個(gè)函數(shù): f1 f2 ,假設(shè) f2 完全沒有提供異常安全保證,即使基本保證也沒有,這就意味著一旦 f2 拋出一個(gè)異常,程序可能會(huì)在 f2 的內(nèi)部發(fā)生資源泄露。這意味著 f2 中可能會(huì)有破損的數(shù)據(jù)結(jié)構(gòu),比如:排好序的數(shù)組可能不再按順序排列,在兩個(gè)數(shù)據(jù)結(jié)構(gòu)之間轉(zhuǎn)送的對(duì)象也可能會(huì)丟失數(shù)據(jù),等等。這樣 someFunc 也無(wú)力回天。如果 someFunc 函數(shù)調(diào)用了沒有提供異常安全保證的函數(shù),那么 someFunc 自身就無(wú)法做出任何保證。

讓我們回到本節(jié)開篇時(shí)所說(shuō)的“孕育生命”的問題。一位女性要么就是懷孕,要么就是沒有,絕沒有“部分懷孕”的狀態(tài)。類似的,一個(gè)軟件系統(tǒng)要么是異常安全的,要么就不是。沒有所謂的“部分異常安全”的狀態(tài)存在。在一個(gè)系統(tǒng)中,即使只有一個(gè)單獨(dú)的函數(shù)不是異常安全的,那么整個(gè)系統(tǒng)也就不是異常安全的。遺憾的是,許多較為古老的 C++ 代碼在編寫的時(shí)候完全沒有考慮到異常安全問題,因此當(dāng)今許多系統(tǒng)便不是異常安全的。新系統(tǒng)中混雜著異常不安全的編寫習(xí)慣。

沒有理由去維持現(xiàn)狀。當(dāng)編寫新代碼或者修改現(xiàn)有代碼的時(shí)候,要認(rèn)真考慮一下如何使之做到異常安全。首先,使用對(duì)象管理資源。(依然參見第 13 條。)這將有效地防止資源泄露。然后對(duì)于你要編寫的每個(gè)函數(shù)確定你要使用哪一層面的異常安全保證,只有在調(diào)用古老的、沒有異常安全保證的代碼時(shí)才放棄異常安全保證,因?yàn)槟銊e無(wú)選擇。記錄下你的選擇,這即是為了你的客戶端程序員,也是為了今后的維護(hù)人員。函數(shù)的異常安全保證位于接口的可見部分,因此你應(yīng)該認(rèn)真規(guī)劃它,就像你認(rèn)真規(guī)劃接口其它部分一樣。

四十年前,人們迷信充斥著 goto 的代碼是完美的,現(xiàn)在我們卻為了編寫結(jié)構(gòu)化控制流而努力。二十年前,全局的完全可訪問的數(shù)據(jù)也是高踞神壇,然而當(dāng)今我們卻在提倡封裝數(shù)據(jù)。十年前,編寫函數(shù)時(shí)不去考慮異常的影響的做法倍受追捧,但是今天,我們堅(jiān)定不渝的編寫異常安全代碼。

歲月荏苒,我們?cè)趯W(xué)習(xí)中不斷進(jìn)步……

銘記在心

異常安全的函數(shù)即使在異常拋出時(shí),也不會(huì)帶來(lái)資源泄露,同時(shí)也不允許數(shù)據(jù)結(jié)構(gòu)遭到破壞。這類函數(shù)提供基本的、增強(qiáng)的、零異常的三個(gè)層面的異常安全保證。

增強(qiáng)保證可以通過復(fù)制并交換策略來(lái)實(shí)現(xiàn),但是增強(qiáng)保證并不是對(duì)所有函數(shù)都適用。

函數(shù)所提供的異常安全保證通常不要強(qiáng)于其調(diào)用的函數(shù)中保證層次最弱的一個(gè)。



[1] 異常規(guī)范是指:在函數(shù)聲明時(shí)列出該函數(shù)可能拋出的異常的類型,并確保該函數(shù)不會(huì)拋出其它類型的異常。——譯者注

[2] 關(guān)于 unexpected 函數(shù)的更多信息,你可以參考你最喜歡的搜索引擎,或者“ C++ 大全”一類的書籍。(搜 set_unexpected 可能會(huì)更好運(yùn)些,因?yàn)樗_定了 unexpected 性質(zhì))

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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一级做a爰片久久| 久久久激情视频| 日韩一级免费| 亚洲欧洲在线一区| 美腿丝袜亚洲色图| 嫩草影视亚洲| 夜夜嗨av色综合久久久综合网 | 欧美在线视屏| 久久精品男女| 亚洲精品一区二区在线观看| 日韩午夜激情av| 欧美一区二区三区另类| 美女尤物久久精品| 国产精品久久久久久超碰| 午夜精品一区二区三区电影天堂 | 亚洲人成网站色ww在线| 亚洲国产精品第一区二区| 亚洲黄色在线观看| 一区二区三区日韩欧美| 久久成人久久爱| 日韩视频永久免费观看| 99精品欧美一区二区蜜桃免费| 一区二区三区四区国产| 久久久精品网| 亚洲精选久久| 久久综合色影院| 亚洲专区免费| 亚洲欧美日韩精品在线| 免费中文字幕日韩欧美| 国产日韩精品一区| 一本色道久久88亚洲综合88| 欧美激情精品久久久| 性做久久久久久久免费看| 欧美三级免费| 亚洲欧美日韩精品久久久久| 亚洲伦理自拍| 亚洲精品日韩久久| 欧美日韩国产成人在线| 亚洲日本欧美| 日韩视频在线免费| 欧美日精品一区视频| 艳妇臀荡乳欲伦亚洲一区| 欧美日产国产成人免费图片| 一区免费观看| 亚洲国产精品精华液2区45| 久久一本综合频道| 亚洲精品中文字幕有码专区| 日韩一本二本av| 国产精品成人观看视频免费 | 久久久综合网| 一区二区在线看| 亚洲第一精品电影| 99综合精品| 黄色成人免费网站| 夜夜嗨av一区二区三区| 国产亚洲欧美另类中文| 亚洲电影自拍| 久久精品夜色噜噜亚洲a∨ | 国内成人在线| 免费观看日韩| 玖玖综合伊人| 欧美激情一区二区三区在线| 亚洲午夜精品久久久久久浪潮| 亚洲欧美一区二区原创| 国内精品久久久久伊人av| 蜜桃久久av一区| 久热精品视频在线观看一区| 久久久久天天天天| 亚洲精品乱码久久久久久日本蜜臀 | 欧美—级a级欧美特级ar全黄| 亚洲一区二区三区在线观看视频| 久久女同互慰一区二区三区| 欧美中文字幕第一页| 欧美精品亚洲一区二区在线播放| 免费一级欧美片在线播放| 国产欧美一区二区三区视频| 亚洲一级免费视频| 久久国产综合精品| 伊人激情综合| 欧美国产先锋| 一区二区电影免费在线观看| 一区二区三区国产精华| 亚洲国产天堂久久国产91| 在线观看精品| 欧美日韩国产麻豆| 一区二区三区四区五区视频 | 久久一区二区三区四区五区| 狠狠色丁香婷婷综合影院 | 西西人体一区二区| 国产日韩av高清| 欧美在线播放一区| 永久免费毛片在线播放不卡| 老**午夜毛片一区二区三区| 亚洲国产精品va| 欧美视频在线免费| 欧美在线视频免费| 亚洲国产一区二区三区a毛片 | 亚洲国产视频直播| 欧美日韩一区二区三区免费看| 99精品视频网| 亚洲第一网站免费视频| 亚洲永久在线| 亚洲乱码视频| 欧美国产视频日韩| 欧美日韩免费| 久久字幕精品一区| 小处雏高清一区二区三区| 亚洲老板91色精品久久| 国产一区二区三区高清在线观看| 久久久亚洲一区| 国产中文一区| 国产日本欧美一区二区三区在线| 国产精品久久影院| 欧美午夜www高清视频| 欧美午夜三级| 欧美午夜片在线观看| 欧美日韩在线视频一区| 欧美日韩亚洲视频| 欧美日韩在线高清| 国产精品嫩草影院av蜜臀| 一区二区日韩免费看| 亚洲精品人人| 亚洲欧美日韩国产| 欧美精品尤物在线| 日韩午夜激情av| 国产欧美日韩免费| 国产精品永久免费| 一区二区三区成人精品| 久久电影一区| 欧美精品久久久久久| 国产麻豆日韩| 韩国精品在线观看| 亚洲人体一区| 在线视频中文亚洲| 国产日本欧美视频| 国产人妖伪娘一区91| 99这里只有久久精品视频| 亚洲小说欧美另类社区| 午夜精品久久久久久久男人的天堂| 日韩视频在线观看国产| 9l国产精品久久久久麻豆| 亚洲欧美日韩中文播放| 另类酷文…触手系列精品集v1小说| 精品成人在线视频| 久久久一区二区三区| 国产精品v欧美精品v日本精品动漫 | 久久九九国产精品| 亚洲国产mv| 亚洲欧美日韩国产成人精品影院| 久久精品国产免费| 国产精品婷婷| 亚洲午夜国产一区99re久久 | 麻豆成人综合网| 亚洲国产精品va在看黑人| 宅男66日本亚洲欧美视频| 久久婷婷国产综合尤物精品 | 久久精品一区二区| 亚洲一区二区视频| 久久精品成人一区二区三区蜜臀 | 亚洲综合另类| 久久精品动漫| 国产欧美一区二区精品性色 | 欧美激情亚洲另类| 国产字幕视频一区二区| 香蕉乱码成人久久天堂爱免费| 亚洲日本在线观看| 欧美日韩午夜激情| 亚洲欧美成人在线| 午夜激情综合网| 99re成人精品视频| 国产精品久久久91| 久久久五月婷婷| 蜜臀av国产精品久久久久| 亚洲在线成人| 欧美日韩一区在线播放| 亚洲色无码播放| 性久久久久久| 亚洲免费观看高清在线观看| 在线视频精品一| 激情懂色av一区av二区av| 亚洲国产国产亚洲一二三| 欧美日韩免费高清一区色橹橹| 亚洲一区二区三区高清| 久久久久国产精品www | 久久国产精品黑丝| 欧美第一黄网免费网站| 久久国产一二区| 欧美精品在线一区二区三区| 欧美成人综合一区| 国产九区一区在线| 亚洲日本中文字幕免费在线不卡| 国产精品制服诱惑| 日韩亚洲欧美精品| 一区二区高清| 久久综合中文色婷婷| 久久精品国产清高在天天线| 欧美日韩成人综合| 亚洲欧洲日产国产网站|