精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

深入理解C++中的異常處理機制

開發 后端
例子看起來還是比較簡單的,但是用處還是很大的,對于賦值操作符來說,很多情況都是需要重載的.

異常處理

增強錯誤恢復能力是提高代碼健壯性的最有力的途徑之一,C語言中采用的錯誤處理方法被認為是緊耦合的,函數的使用者必須在非常靠近函數調用的地方編 寫錯誤處理代碼,這樣會使得其變得笨拙和難以使用。C++中引入了異常處理機制,這是C++的主要特征之一,是考慮問題和處理錯誤的一種更好的方式。使用 錯誤處理可以帶來一些優點,如下:

  • 錯誤處理代碼的編寫不再冗長乏味,并且不再和正常的代碼混合在一起,程序員只需要編寫希望產生的代碼,然后在后面某個單獨的區段里編寫處理錯誤的嗲嗎。多次調用同一個函數,則只需要某個地方編寫一次錯誤處理代碼。

  • 錯誤不能被忽略,如果一個函數必須向調用者發送一次錯誤信息。它將拋出一個描述這個錯誤的對象。

傳統的錯誤處理和異常處理

在討論異常處理之前,我們先談談C語言中的傳統錯誤處理方法,這里列舉了如下三種:

  • 在函數中返回錯誤,函數會設置一個全局的錯誤狀態標志。

  • 使用信號來做信號處理系統,在函數中raise信號,通過signal來設置信號處理函數,這種方式耦合度非常高,而且不同的庫產生的信號值可能會發生沖突

  • 使用標準C庫中的非局部跳轉函數 setjmp和longjmp ,這里使用setjmp和longjmp來演示下如何進行錯誤處理:

  1. #include <iostream> 
  2. #include <setjmp.h> 
  3. jmp_buf static_buf; //用來存放處理器上下文,用于跳轉 
  4.  
  5. void do_jmp() 
  6.     //do something,simetime occurs a little error 
  7.     //調用longjmp后,會載入static_buf的處理器信息,然后第二個參數作為返回點的setjmp這個函數的返回值 
  8.     longjmp(static_buf,10);//10是錯誤碼,根據這個錯誤碼來進行相應的處理 
  9.  
  10. int main() 
  11.     int ret = 0
  12.     //將處理器信息保存到static_buf中,并返回0,相當于在這里做了一個標記,后面可以跳轉過來 
  13.     if((ret = setjmp(static_buf)) == 0) { 
  14.         //要執行的代碼 
  15.         do_jmp(); 
  16.     } else {    //出現了錯誤 
  17.         if (ret == 10
  18.             std::cout << "a little error" << std::endl; 
  19.     } 

錯誤處理方式看起來耦合度不是很高,正常代碼和錯誤處理的代碼分離了,處理處理的代碼都匯聚在一起了。但是基于這種局部跳轉的方式來處理代碼,在 C++中卻存在很嚴重的問題,那就是對象不能被析構,局部跳轉后不會主動去調用已經實例化對象的析構函數。這將導致內存泄露的問題。下面這個例子充分顯示 了這點

  1. #include <iostream> 
  2. #include <csetjmp> 
  3.  
  4. using namespace std; 
  5.  
  6. class base { 
  7.     public
  8.         base() { 
  9.             cout << "base construct func call" << endl; 
  10.         } 
  11.         ~base() { 
  12.             cout << "~base destruct func call" << endl; 
  13.         } 
  14. }; 
  15.  
  16. jmp_buf static_buf; 
  17.  
  18. void test_base() { 
  19.     base b; 
  20.     //do something 
  21.     longjmp(static_buf,47);//進行了跳轉,跳轉后會發現b無法析構了 
  22.  
  23. int main() { 
  24.     if(setjmp(static_buf) == 0) { 
  25.         cout << "deal with some thing" << endl; 
  26.         test_base(); 
  27.     } else { 
  28.         cout << "catch a error" << endl; 
  29.     } 

在上面這段代碼中,只有base類的構造函數會被調用,當longjmp發生了跳轉后,b這個實例將不會被析構掉,但是執行流已經無法回到這里,b 這個實例將不會被析構。這就是局部跳轉用在C++中來處理錯誤的時候帶來的一些問題,在C++中異常則不會有這些問題的存在。那么接下來看看如何定義一個 異常,以及如何拋出一個異常和捕獲異常吧.

異常的拋出

  1. class MyError { 
  2.     const charconst data; 
  3. public
  4.     MyError(const charconst msg = 0):data(msg) 
  5.     { 
  6.         //idle 
  7.     } 
  8. }; 
  9.  
  10. void do_error() { 
  11.     throw MyError("something bad happend"); 
  12.  
  13. int main() 
  14.     do_error(); 

上面的例子中,通過throw拋出了一個異常類的實例,這個異常類,可以是任何一個自定義的類,通過實例化傳入的參數可以表明發生的錯誤信息。其實 異常就是一個帶有異常信息的類而已。異常被拋出后,需要被捕獲,從而可以從錯誤中進行恢復,那么接下來看看如何去捕獲一個異常吧。在上面這個例子中使用拋 出異常的方式來進行錯誤處理相比與之前使用局部跳轉的實現來說,***的不同之處就是異常拋出的代碼塊中,對象會被析構,稱之為堆棧反解.

異常的捕獲

C++中通過catch關鍵字來捕獲異常,捕獲異常后可以對異常進行處理,這個處理的語句塊稱為異常處理器。下面是一個簡單的捕獲異常的例子:

  1. try
  2.     //do something 
  3.     throw string("this is exception"); 
  4. catch(const string& e) { 
  5.     cout << "catch a exception " << e << endl; 

catch有點像函數,可以有一個參數,throw拋出的異常對象,將會作為參數傳遞給匹配到到catch,然后進入異常處理器,上面的代碼僅僅是 展示了拋出一種異常的情況,加入try語句塊中有可能會拋出多種異常的,那么該如何處理呢,這里是可以接多個catch語句塊的,這將導致引入另外一個問 題,那就是如何進行匹配。

異常的匹配

異常的匹配我認為是符合函數參數匹配的原則的,但是又有些不同,函數匹配的時候存在類型轉換,但是異常則不然,在匹配過程中不會做類型的轉換,下面的例子說明了這個事實:

  1. #include <iostream> 
  2.  
  3. using namespace std; 
  4. int main() 
  5.     try
  6.  
  7.         throw 'a'
  8.     }catch(int a) { 
  9.         cout << "int" << endl; 
  10.     }catch(char c) { 
  11.         cout << "char" << endl; 
  12.     } 

上面的代碼的輸出結果是char,因為拋出的異常類型就是char,所以就匹配到了第二個異常處理器。可以發現在匹配過程中沒有發生類型的轉換。將 char轉換為int。盡管異常處理器不做類型轉換,但是基類可以匹配到派生類這個在函數和異常匹配中都是有效的,但是需要注意catch的形參需要是引 用類型或者是指針類型,否則會 導致切割派生類這個問題。

  1. //基類 
  2. class Base{ 
  3.     public
  4.         Base(string msg):m_msg(msg) 
  5.         { 
  6.         } 
  7.         virtual void what(){ 
  8.             cout << m_msg << endl; 
  9.         } 
  10.     void test() 
  11.     { 
  12.         cout << "I am a CBase" << endl; 
  13.     } 
  14.     protected
  15.         string m_msg; 
  16. }; 
  17. //派生類,重新實現了虛函數 
  18. class CBase : public Base 
  19.     public
  20.         CBase(string msg):Base(msg) 
  21.         { 
  22.  
  23.         } 
  24.         void what() 
  25.         { 
  26.            cout << "CBase:" << m_msg << endl; 
  27.         } 
  28. }; 
  29.  
  30. int main() 
  31.     try { 
  32.         //do some thing 
  33.     //拋出派生類對象 
  34.         throw CBase("I am a CBase exception"); 
  35.  
  36.     }catch(Base& e) {  //使用基類可以接收 
  37.         e.what(); 
  38.     } 

上面的這段代碼可以正常的工作,實際上我們日常編寫自己的異常處理函數的時候也是通過繼承標準異常來實現字節的自定義異常的,但是如果將 Base&換成Base的話,將會導致對象被切割,例如下面這段代碼將會編譯出錯,因為CBase被切割了,導致CBase中的test函數無法 被調用。

  1. try { 
  2.     //do some thing 
  3.     throw CBase("I am a CBase exception"); 
  4.  
  5. }catch(Base e) { 
  6.     e.test(); 

到此為此,異常的匹配算是說清楚了,總結一下,異常匹配的時候基本上遵循下面幾條規則:

異常匹配除了必須要是嚴格的類型匹配外,還支持下面幾個類型轉換.

  • 允許非常量到常量的類型轉換,也就是說可以拋出一個非常量類型,然后使用catch捕捉對應的常量類型版本

  • 允許從派生類到基類的類型轉換

  • 允許數組被轉換為數組指針,允許函數被轉換為函數指針

假想一種情況,當我要實現一代代碼的時候,希望無論拋出什么類型的異常我都可以捕捉到,目前來說我們只能寫上一大堆的catch語句捕獲所有可能在 代碼中出現的異常來解決這個問題,很顯然這樣處理起來太過繁瑣,幸好C++提供了一種可以捕捉任何異常的機制,可以使用下列代碼中的語法。

   catch(...) {
    //異常處理器,這里可以捕捉任何異常,帶來的問題就是無法或者異常信息
   }

如果你要實現一個函數庫,你捕捉了你的函數庫中的一些異常,但是你只是記錄日志,并不去處理這些異常,處理異常的事情會交給上層調用的代碼來處理.對于這樣的一個場景C++也提供了支持.

  1. try
  2.     throw Exception("I am a exception");    
  3. }catch(...) { 
  4.     //log the exception 
  5.     throw

通過在catch語句塊中加入一個throw,就可以把當前捕獲到的異常重新拋出.在異常拋出的那一節中,我在代碼中拋出了一個異常,但是我沒有使用任何catch語句來捕獲我拋出的這個異常,執行上面的程序會出現下面的結果.

  1. terminate called after throwing an instance of 'MyError' 
  2. Aborted (core dumped) 

為什么會出現這樣的結果呢?,當我們拋出一個異常的時候,異常會隨著函數調用關系,一級一級向上拋出,直到被捕獲才會停止,如果最終沒有被捕獲將會 導致調用terminate函數,上面的輸出就是自動調用terminate函數導致的,為了保證更大的靈活性,C++提供了set_terminate 函數可以用來設置自己的terminate函數.設置完成后,拋出的異常如果沒有被捕獲就會被自定義的terminate函數進行處理.下面是一個使用的 例子:

  1. #include <exception> 
  2. #include <iostream> 
  3. #include <cstdlib> 
  4. using namespace std; 
  5.  
  6. class MyError { 
  7.     const charconst data; 
  8. public
  9.     MyError(const charconst msg = 0):data(msg) 
  10.     { 
  11.         //idle 
  12.     } 
  13. }; 
  14.  
  15. void do_error() { 
  16.     throw MyError("something bad happend"); 
  17. //自定義的terminate函數,函數原型需要一致 
  18. void terminator() 
  19.     cout << "I'll be back" << endl; 
  20.     exit(0); 
  21.  
  22. int main() 
  23.     //設置自定義的terminate,返回的是原有的terminate函數指針 
  24.     void (*old_terminate)() = set_terminate(terminator); 
  25.     do_error(); 
  26. 上面的代碼會輸出I'll be back 

到此為此關于異常匹配的我所知道的知識點都已經介紹完畢了,那么接著可以看看下一個話題,異常中的資源清理.

異常中的資源清理

在談到局部跳轉的時候,說到局部調轉不會調用對象的析構函數,會導致內存泄露的問題,C++中的異常則不會有這個問題,C++中通過堆棧反解將已經 定義的對象進行析構,但是有一個例外就是構造函數中如果出現了異常,那么這會導致已經分配的資源無法回收,下面是一個構造函數拋出異常的例子:

  1. #include <iostream> 
  2. #include <string> 
  3. using namespace std; 
  4.  
  5. class base 
  6.     public
  7.         base() 
  8.         { 
  9.             cout << "I start to construct" << endl; 
  10.             if (count == 3//構造第四個的時候拋出異常 
  11.                 throw string("I am a error"); 
  12.             count++; 
  13.         } 
  14.  
  15.         ~base() 
  16.         { 
  17.             cout << "I will destruct " << endl; 
  18.         } 
  19.     private
  20.         static int count; 
  21. }; 
  22.  
  23. int base::count = 0
  24.  
  25. int main() 
  26.         try
  27.  
  28.             base test[5]; 
  29.  
  30.         } catch(...){ 
  31.  
  32.             cout << "catch some error" << endl; 
  33.  
  34.         } 
  35. 上面的代碼輸出結果是: 
  36. I start to construct 
  37. I start to construct 
  38. I start to construct 
  39. I start to construct 
  40. I will destruct 
  41. I will destruct 
  42. I will destruct 
  43. catch some error 

在上面的代碼中構造函數發生了異常,導致對應的析構函數沒有執行,因此實際編程過程中應該避免在構造函數中拋出異常,如果沒有辦法避免,那么一定要 在構造函數中對其進行捕獲進行處理.***介紹一個知識點就是函數try語句塊,如果main函數可能會拋出異常該怎么捕獲?,如果構造函數中的初始化列表 可能會拋出異常該怎么捕獲?下面的兩個例子說明了函數try語句塊的用法:

  1. #include <iostream> 
  2.  
  3. using namespace std; 
  4.  
  5. int main() try { 
  6.     throw "main"
  7. catch(const char* msg) { 
  8.     cout << msg << endl; 
  9.     return 1
  10. main函數語句塊,可以捕獲main函數中拋出的異常. 
  11. class Base 
  12.     public
  13.         Base(int data,string str)try:m_int(data),m_string(str)//對初始化列表中可能會出現的異常也會進行捕捉 
  14.        { 
  15.             // some initialize opt 
  16.        }catch(const char* msg) { 
  17.  
  18.             cout << "catch a exception" << msg << endl; 
  19.        } 
  20.  
  21.     private
  22.         int m_int; 
  23.         string m_string; 
  24. }; 
  25.  
  26. int main() 
  27.     Base base(1,"zhangyifei"); 

上面說了很多都是關于異常的使用,如何定義自己的異常,編寫異常是否應該遵循一定的標準,在哪里使用異常,異常是否安全等等一系列的問題,下面會一一討論的.

標準異常

C++標準庫給我們提供了一系列的標準異常,這些標準異常都是從exception類派生而來,主要分為兩大派生類,一類是 logic_error,另一類則是runtime_error這兩個類在stdexcept頭文件中,前者主要是描述程序中出現的邏輯錯誤,例如傳遞了 無效的參數,后者指的是那些無法預料的事件所造成的錯誤,例如硬件故障或內存耗盡等,這兩者都提供了一個參數類型為std::string的構造函數,這 樣就可以將異常信息保存起來,然后通過what成員函數得到異常信息.

  1. #include <stdexcept> 
  2. #include <iostream> 
  3. #include <string> 
  4. using namespace std; 
  5.  
  6. class MyError:public runtime_error { 
  7. public
  8.     MyError(const string& msg = "") : runtime_error(msg) {} 
  9.  
  10. }; 
  11.  
  12. //runtime_error logic_error 兩個都是繼承自標準異常,帶有string構造函數 
  13. // 
  14. int main() 
  15.     try { 
  16.         throw MyError("my message");   
  17.     }   catch(MyError& x) { 
  18.         cout << x.what() << endl;    
  19.     } 

異常規格說明

假設一個項目中使用了一些第三方的庫,那么第三方庫中的一些函數可能會拋出異常,但是我們不清楚,那么C++提供了一個語法,將一個函數可能會拋出 的異常列出來,這樣我們在編寫代碼的時候參考函數的異常說明即可,但是C++11中這中異常規格說明的方案已經被取消了,所以我不打算過多介紹,通過一個 例子看看其基本用法即可,重點看看C++11中提供的異常說明方案:

  1. #include <exception> 
  2. #include <iostream> 
  3. #include <cstdio> 
  4. #include <cstdlib> 
  5. using namespace std; 
  6.  
  7. class Up{}; 
  8. class Fit{}; 
  9. void g(); 
  10. //異常規格說明,f函數只能拋出Up 和Fit類型的異常 
  11. void f(int i)throw(Up,Fit) { 
  12.     switch(i) { 
  13.         case 1throw Up(); 
  14.         case 2throw Fit();    
  15.     } 
  16.     g(); 
  17.  
  18. void g() {throw 47;} 
  19.  
  20. void my_ternminate() { 
  21.     cout << "I am a ternminate" << endl; 
  22.     exit(0); 
  23.  
  24. void my_unexpected() { 
  25.     cout << "unexpected exception thrown" << endl; 
  26. //   throw Up(); 
  27.     throw 8
  28.     //如果在unexpected中繼續拋出異常,拋出的是規格說明中的 則會被捕捉程序繼續執行 
  29.     //如果拋出的異常不在異常規格說明中分兩種情況 
  30.     //1.異常規格說明中有bad_exception ,那么會導致拋出一個bad_exception 
  31.     //2.異常規格說明中沒有bad_exception 那么會導致程序調用ternminate函數 
  32.    // exit(0); 
  33.  
  34. int main() { 
  35. set_terminate(my_ternminate); 
  36. set_unexpected(my_unexpected); 
  37. for(int i = 1;i <=3;i++) 
  38.      //當拋出的異常,并不是異常規格說明中的異常時 
  39.      //會導致最終調用系統的unexpected函數,通過set_unexpected可以 
  40.      //用來設置自己的unexpected汗函數 
  41.     try { 
  42.         f(i);    
  43.     }catch(Up) { 
  44.         cout << "Up caught" << endl;    
  45.     }catch(Fit) { 
  46.         cout << "Fit caught" << endl;    
  47.     }catch(bad_exception) { 
  48.         cout << "bad exception" << endl;    
  49.     } 

上面的代碼說明了異常規格說明的基本語法,以及unexpected函數的作用,以及如何自定義自己的unexpected函數,還討論了在 unexpected函數中繼續拋出異常的情況下,該如何處理拋出的異常.C++11中取消了這種異常規格說明.引入了一個noexcept函數,用于表 明這個函數是否會拋出異常

void recoup(int) noexecpt(true);  //recoup不會拋出異常
void recoup(int) noexecpt(false); //recoup可能會拋出異常

此外還提供了noexecpt用來檢測一個函數是否不拋出異常.

異常安全

異常安全我覺得是一個挺復雜的點,不光光需要實現函數的功能,還要保存函數不會在拋出異常的情況下,出現不一致的狀態.這里舉一個例子,大家在實現 堆棧的時候經常看到書中的例子都是定義了一個top函數用來獲得棧頂元素,還有一個返回值是void的pop函數僅僅只是把棧頂元素彈出,那么為什么沒有 一個pop函數可以 即彈出棧頂元素,并且還可以獲得棧頂元素呢?

  1. template<typename T> T stack<T>::pop() 
  2.     if(count == 0
  3.         throw logic_error("stack underflow"); 
  4.     else 
  5.         return data[--count]; 

如果函數在***一行拋出了一個異常,那么這導致了函數沒有將退棧的元素返回,但是Count已經減1了,所以函數希望得到的棧頂元素丟失了.本質原 因是因為這個函數試圖一次做兩件事,1.返回值,2.改變堆棧的狀態.***將這兩個獨立的動作放到兩個獨立的函數中,遵守內聚設計的原則,每一個函數只做 一件事.我們 再來討論另外一個異常安全的問題,就是很常見的賦值操作符的寫法,如何保證賦值操作是異常安全的.

  1. class Bitmap {...}; 
  2. class Widget { 
  3.     ... 
  4. private
  5.     Bitmap *pb; 
  6.  
  7. }; 
  8. Widget& Widget::operator=(const Widget& rhs) 
  9.     delete pb; 
  10.     pb = new Bitmap(*rhs.pb); 
  11.     return *this

上面的代碼不具備自我賦值安全性,倘若rhs就是對象本身,那么將會導致*rhs.pb指向一個被刪除了的對象.那么就緒改進下.加入證同性測試.

  1. Widget& Widget::operator=(const Widget& rhs) 
  2.     If(this == rhs) return *this//證同性測試 
  3.     delete pb; 
  4.     pb = new Bitmap(*rhs.pb); 
  5.     return *this

但是現在上面的代碼依舊不符合異常安全性,因為如果delete pb執行完成后在執行new Bitmap的時候出現了異常,則會導致最終指向一塊被刪除的內存.現在只要稍微改變一下,就可以讓上面的代碼具備異常安全性.

  1. Widget& Widget::operator=(const Widget& rhs) 
  2.     If(this == rhs) return *this//證同性測試 
  3.     Bitmap *pOrig = pb; 
  4.     pb = new Bitmap(*rhs.pb); //現在這里即使發生了異常,也不會影響this指向的對象 
  5.     delete pOrig; 
  6.     return *this;   

這個例子看起來還是比較簡單的,但是用處還是很大的,對于賦值操作符來說,很多情況都是需要重載的.

 

 

責任編輯:王雪燕 來源: zhangyifei216
相關推薦

2024-02-27 10:48:16

C++代碼開發

2025-01-09 12:01:53

2011-03-17 09:20:05

異常處理機制

2009-08-05 18:09:17

C#異常處理機制

2021-03-25 07:44:39

C++異常處理開發技術

2023-10-04 00:04:00

C++extern

2024-04-10 12:14:36

C++指針算術運算

2023-12-31 12:56:02

C++內存編程

2022-05-06 16:18:00

Block和 C++OC 類lambda

2024-04-11 14:04:23

C++編程函數

2017-05-03 17:00:16

Android渲染機制

2017-01-13 22:42:15

iosswift

2024-03-28 18:12:28

指針函數指針C++

2023-09-12 11:44:02

C++數據對齊

2025-06-09 01:15:00

2024-03-04 10:00:35

數據庫處理機制

2011-04-06 10:27:46

Java異常處理

2023-10-31 10:51:56

MySQLMVCC并發性

2011-07-21 15:20:41

java異常處理機制

2017-01-12 19:34:58

點贊
收藏

51CTO技術棧公眾號

亚洲国产精品尤物yw在线观看| 国产在线麻豆精品观看| 亚洲欧洲国产伦综合| 五月婷婷之综合激情| 国产区在线观看| 99re热视频精品| 国产精品永久免费| 国产在线拍揄自揄拍无码视频| 岳的好大精品一区二区三区| 欧美精品一级二级| 男女日批视频在线观看| 大地资源中文在线观看免费版| 国产在线精品一区在线观看麻豆| 欧洲永久精品大片ww免费漫画| 东京热无码av男人的天堂| 2023国产精华国产精品| 欧美三区在线观看| 男女超爽视频免费播放| 浪潮av一区| 久久久久久久久99精品| 国产不卡一区二区三区在线观看| 九九热最新视频| 亚洲黄色影片| 麻豆国产va免费精品高清在线| 三叶草欧洲码在线| 欧美影院精品| 欧美日韩一卡二卡| 成人免费在线小视频| 自拍亚洲图区| 国产精品毛片高清在线完整版 | 久久国产视频一区| 午夜欧美在线| 国产午夜精品一区理论片飘花| 91精品又粗又猛又爽| 亚洲电影二区| 欧美色手机在线观看| 国产一区二区三区精彩视频| 男女视频在线| 亚洲欧美激情在线| 视频一区亚洲| 欧美视频综合| 91麻豆6部合集magnet| 成人黄色片视频网站| 国产精品久久久久久久久久久久久久久久| 午夜一区不卡| 2018中文字幕一区二区三区| 国产亚洲精久久久久久无码77777| 国产精品99久久精品| 一区二区在线视频| 国产又粗又猛又爽视频| 欧美调教在线| 日韩电影免费观看在线观看| 国产伦精品一区二区三区精品| 亚洲高清999| 欧美电影免费观看完整版| 中文字幕55页| 日韩成人视屏| 欧美成人bangbros| 日韩成人av影院| 高清一区二区三区| 日韩成人av网| 泷泽萝拉在线播放| 九九综合久久| 在线观看中文字幕亚洲| 亚洲精品自拍视频在线观看| 香蕉国产精品| 九色精品免费永久在线| 久久久久久久久久99| 国产精品黄色| 午夜精品在线观看| 精品欧美一区二区三区免费观看| 久久精品毛片| 国产精品久久久久免费a∨| 羞羞色院91蜜桃| 久久99精品久久久久久动态图| 91久久国产精品| 亚洲国产精品久久人人爱潘金莲| 成人av网址在线| 久久久久一区二区| 超碰国产在线观看| 亚洲丝袜另类动漫二区| 国产精品日韩三级| 久久影院午夜精品| 在线视频亚洲一区| 日韩欧美理论片| 久久国产精品色av免费看| 亚洲免费影视第一页| 国产99在线 | 亚洲| 2023国产精品久久久精品双| 国产做受高潮69| 蜜臀尤物一区二区三区直播| 国产在线视频不卡二| 国产精品一级久久久| 韩国三级av在线免费观看| 亚洲天堂精品在线观看| 国内精品视频一区二区三区| 一区二区电影免费观看| 欧美日韩高清一区| 成人区人妻精品一区二| 欧美久久综合网| 国内精品一区二区三区| 伊人网综合在线| 国产91精品一区二区麻豆亚洲| 欧洲精品久久| 免费不卡av| 欧美日韩久久久| 污污内射在线观看一区二区少妇| 大片网站久久| 97国产真实伦对白精彩视频8| 亚洲视频在线免费播放| 99久久精品情趣| 在线视频一二三区| 大胆人体一区二区| 精品少妇一区二区三区免费观看 | 午夜av免费观看| 亚洲欧洲日产国码二区| av观看免费在线| 成人精品动漫一区二区三区| 日韩在线视频导航| 黄色片中文字幕| 成人免费看的视频| 色一情一乱一乱一区91| 成人免费网站www网站高清| 精品国产91久久久久久久妲己 | 日本女人黄色片| 精品国精品国产自在久国产应用| 97在线视频观看| 午夜老司机福利| 亚洲欧美日韩国产一区二区三区| 日本免费黄视频| 成人线上播放| 欧美成人午夜激情| 一级淫片免费看| 国产女人18水真多18精品一级做| av免费观看网| 精品国产乱子伦一区二区| 九九热这里只有在线精品视| 国产精品久久久久久无人区| 亚洲国产高清不卡| 久草青青在线观看| 欧美日韩一区二区三区在线电影 | 国产一级视频在线| 国产麻豆91精品| 中文字幕中文字幕在线中一区高清 | 国产一区深夜福利| 亚洲人午夜射精精品日韩| 香蕉成人啪国产精品视频综合网 | 久久久久99精品成人片三人毛片| 成人av在线播放网址| 日韩在线观看a| 911精品国产| 欧美激情亚洲一区| 亚洲国产欧美另类| 亚洲一区二区四区蜜桃| 国产chinesehd精品露脸| 欧美精品麻豆| 国产98在线|日韩| 欧美videosex性欧美黑吊| 日韩一区二区三区在线| 91aaa在线观看| 丰满白嫩尤物一区二区| 国产美女在线一区| 欧美精品中文| 国产成人免费av| 1024国产在线| 91精品国产综合久久精品麻豆| 亚洲色图综合区| 懂色av噜噜一区二区三区av| 777精品久无码人妻蜜桃| 久久99性xxx老妇胖精品| 国产精品美乳一区二区免费| 看黄网站在线| 精品日韩一区二区| 久久夜靖品2区| 国产欧美一区二区精品性色| 57pao国产成永久免费视频| 午夜日本精品| 精品蜜桃一区二区三区| 欧美日韩五区| 久久久精品网站| 天堂网在线观看视频| 欧美性猛交xxxxxx富婆| 老女人性淫交视频| 久久奇米777| 91精品999| 99在线观看免费视频精品观看| 色一情一乱一伦一区二区三区丨 | 国产欧美一区二区三区另类精品| 免费高潮视频95在线观看网站| 亚洲视频电影图片偷拍一区| 国产又大又粗又硬| 欧美日韩精品国产| 国产午夜精品久久久久久久久| 国产成人免费视频一区| 国产亚洲综合视频| 99九九热只有国产精品| 国产欧美欧洲| 五月天色综合| 2019精品视频| 爆操欧美美女| 亚洲网址你懂得| 成人小说亚洲一区二区三区| 欧美伊人久久久久久午夜久久久久| 印度午夜性春猛xxx交| 久久婷婷成人综合色| 久久人人爽人人片| 日韩一区精品视频| 全黄性性激高免费视频| 天天综合国产| 神马影院一区二区三区| 精品久久97| 成人精品久久久| 在线手机中文字幕| 久久99久久99精品免观看粉嫩| 国产精品久久久久久久龚玥菲| 亚洲国产精品成人一区二区| 97人妻人人澡人人爽人人精品| 色天天综合久久久久综合片| 久久久久性色av无码一区二区| 国产日韩高清在线| 一级特级黄色片| 国产v综合v亚洲欧| 夜夜夜夜夜夜操| 日本亚洲免费观看| 欧美日韩在线一| 欧美日韩蜜桃| dy888午夜| 色小子综合网| 亚洲精品中文字幕在线| 国产亚洲一区二区三区不卡| 久久国产欧美精品| 粉嫩的18在线观看极品精品| 99久久自偷自偷国产精品不卡| 国产一区二区三区| 91精品国产综合久久久久久久久 | 欧美日韩黄视频| 看黄色一级大片| 欧美视频免费在线| 久久精品久久国产| 亚洲综合一区在线| 免费在线观看一级片| 中文字幕一区在线观看视频| 国产成人精品视频免费| 欧美国产激情二区三区| 高清国产在线观看| 久久精品欧美日韩精品| 色婷婷av777| 久久老女人爱爱| 在哪里可以看毛片| 久久久精品国产免大香伊| 无码人妻精品一区二区三区温州| 91网站最新网址| 激情综合丁香五月| 91年精品国产| 成人免费av片| 国产亚洲欧美日韩日本| 国产黄色大片免费看| 日本一区二区不卡视频| 日本一区二区视频在线播放| 国产精品久久久久三级| 国产大屁股喷水视频在线观看| 中文字幕在线观看一区| 国产十六处破外女视频| 亚洲国产日韩av| 国产成人自拍视频在线| 一本大道综合伊人精品热热| 午夜一级黄色片| 欧美日韩成人一区| 99热这里只有精品9| 亚洲二区中文字幕| 免费在线黄色电影| 中文字幕亚洲欧美在线| caopen在线视频| 97超碰国产精品女人人人爽| 九九热线视频只有这里最精品| 国产精品香蕉av| 三级欧美日韩| 欧美精品一区在线发布| 99久久视频| 可以看毛片的网址| 老司机免费视频久久| 久久成年人网站| 91丨porny丨首页| 一本色道久久88| 亚洲一级二级三级在线免费观看| 久久久蜜桃一区二区| 制服丝袜日韩国产| 天天干视频在线观看| 色黄久久久久久| 国产色播av在线| 成人h猎奇视频网站| 爱高潮www亚洲精品| 婷婷久久伊人| 黄色欧美日韩| 久热精品在线播放| a级精品国产片在线观看| 91成人精品一区二区| 亚洲福利视频三区| 艳妇乳肉豪妇荡乳av无码福利 | 国产日韩欧美成人| 高清精品视频| 一区中文字幕在线观看| 亚洲欧美清纯在线制服| www.日本久久| 国产三级一区二区| 久草视频免费在线播放| 欧美日韩性生活| 神马精品久久| 欧美久久精品一级黑人c片| 我爱我色成人网| 国产一区免费在线| 亚洲综合色站| 国产又猛又黄的视频| av在线不卡免费看| 天天综合天天做| 欧美视频第二页| 你懂的在线免费观看| 久久久久久欧美| 国产一区一区| 在线不卡日本| 免费一区二区视频| 极品粉嫩小仙女高潮喷水久久| 一区二区三区中文字幕| 夜夜嗨av禁果av粉嫩avhd| 亚洲人成在线免费观看| 特黄毛片在线观看| 国产精品一区二区三区在线| 欧美视频亚洲视频| www.国产福利| 亚洲欧美另类久久久精品| 一本一道精品欧美中文字幕| 在线播放日韩欧美| 写真福利精品福利在线观看| 久久久综合香蕉尹人综合网| 亚洲乱码久久| 插我舔内射18免费视频| 亚洲一区二区在线视频| 丰满肉嫩西川结衣av| 欧美美女18p| 国产精品一区二区三区四区在线观看| 亚洲乱码一区二区三区三上悠亚| 久热re这里精品视频在线6| 日韩人妻无码一区二区三区| 欧美色另类天堂2015| 三级在线电影| 奇米影视亚洲狠狠色| 国产亚洲一区| 日韩一级理论片| 国产精品水嫩水嫩| 中文字幕一区二区三区免费看| 中文字幕国产日韩| 国产三级一区| 在线观看日本一区| 国产精品综合av一区二区国产馆| 69av视频在线| 亚洲国产精品99| 日韩国产激情| 亚洲一区二区三区精品视频| 韩国三级中文字幕hd久久精品| 精品国产乱码久久久久久鸭王1| 欧美xfplay| 日本在线播放一二三区| 青青草原成人| 精品一区二区在线免费观看| 欧美成人国产精品高潮| 亚洲高清久久久久久| 中日韩脚交footjobhd| 日韩国产一区久久| 另类小说综合欧美亚洲| 劲爆欧美第一页| 亚洲精选在线观看| 成人一级视频| www.-级毛片线天内射视视| 成人在线视频首页| www.国产一区二区| 日韩亚洲综合在线| 大奶一区二区三区| 亚洲视频在线a| 亚洲精品一二三| 深夜福利视频网站| 国产精品电影观看| 女人天堂亚洲aⅴ在线观看| 好吊一区二区三区视频| 欧美午夜一区二区三区免费大片| 9191在线播放| 欧美极品jizzhd欧美| 国产一区不卡视频| 欧美亚洲精品天堂| 日韩视频精品在线| 国产精品2023| 日日干夜夜操s8| 舔着乳尖日韩一区| 95在线视频| 精品国产乱码久久久久| 久久精品国产一区二区| 日韩免费一级片| 久久精品国产久精国产一老狼 | 日韩精品中文字幕视频在线| 婷婷丁香久久| 欧美精品一区二区三区免费播放|