亚洲有码Av一区二区三区_国产高清啪啪免费视频_69色视频国产_国产成人人人爆出白浆_国产精品自在线拍国_一本久久伊人热热精品无码_午夜性刺激在线看免费带字幕_助力高品质欧美狂喷水_亚洲精品日韩无码_精品无码一区二区三区蜜臀_麻豆高清国产AV_熟妇人素无码中文字幕_亚洲a级片在线观看_国产欧美日韩三区_99国产成人高清在线观看

ARTICLE DETAIL

資訊詳情

深耕商務(wù)建站與企業(yè)官網(wǎng)運(yùn)營(yíng)的一線實(shí)戰(zhàn)洞察。

手寫C++ STL list容器:迭代器、內(nèi)存管理與STL風(fēng)格實(shí)戰(zhàn)解析

手寫C++ STL list容器:迭代器、內(nèi)存管理與STL風(fēng)格實(shí)戰(zhàn)解析 1. 整體設(shè)計(jì)與思路拆解1.1 為什么選list作為模擬實(shí)現(xiàn)的切入點(diǎn)學(xué)習(xí)C的人遲早會(huì)碰到同一個(gè)問(wèn)題STL容器底層到底是怎么寫的項(xiàng)目標(biāo)題說(shuō)得很直接——手寫一個(gè)list容器把迭代器、構(gòu)造函數(shù)和STL風(fēng)格編程全部串起來(lái)。我的建議是如果你只打算手寫一個(gè)STL容器來(lái)加深理解首選list而不是vector。原因在于vector的連續(xù)內(nèi)存特性會(huì)把很多細(xì)節(jié)掩蓋掉插入刪除要搬移元素實(shí)現(xiàn)上反而顯得“直覺(jué)化”list是雙向鏈表節(jié)點(diǎn)之間靠指針串聯(lián)結(jié)構(gòu)更清晰天然逼迫你去處理指針、節(jié)點(diǎn)生命周期、迭代器封裝這些STL最核心的問(wèn)題。把這些搞明白再回頭看vector、deque甚至哈希表都會(huì)順利很多。這里還要澄清一個(gè)認(rèn)知list不是簡(jiǎn)單地在C里寫一個(gè)“節(jié)點(diǎn)指針”的鏈表就完事了。真正的STL風(fēng)格list至少要有allocator內(nèi)存分配器、迭代器包括const版本和反向迭代器、完整的構(gòu)造/拷貝/移動(dòng)/析構(gòu)家族、O(1)的insert/erase、以及“插入不影響其他迭代器、刪除只影響被刪迭代器”這樣的行為保證。模擬實(shí)現(xiàn)的價(jià)值在于你不是重復(fù)造一個(gè)能跑的產(chǎn)品輪子而是理解產(chǎn)品輪子為什么長(zhǎng)這樣。項(xiàng)目標(biāo)題把“構(gòu)造”單獨(dú)拿出來(lái)我覺(jué)得特別對(duì)——很多人以為list實(shí)現(xiàn)的大頭是鏈表操作其實(shí)構(gòu)造家族才最容易翻車拷貝構(gòu)造、拷貝賦值、移動(dòng)構(gòu)造、析構(gòu)之間的配合一旦出錯(cuò)程序會(huì)在莫名其妙的地方崩潰而且很難查。1.2 核心結(jié)構(gòu)節(jié)點(diǎn)、哨兵與三指針模型動(dòng)手寫之前先把紙面上的東西定下來(lái)。STL的list是雙向鏈表每個(gè)節(jié)點(diǎn)至少有兩個(gè)指針prev指向前驅(qū)next指向后繼。標(biāo)準(zhǔn)庫(kù)實(shí)際使用的list還有一個(gè)關(guān)鍵設(shè)計(jì)——哨兵頭節(jié)點(diǎn)dummy node。鏈表里總是保留一個(gè)不存儲(chǔ)有效數(shù)據(jù)的頭節(jié)點(diǎn)它的next指向第一個(gè)有效節(jié)點(diǎn)沒(méi)有則為nullptrprev指向最后一個(gè)有效節(jié)點(diǎn)沒(méi)有則為nullptr。有哨兵的好處是空鏈表和非空鏈表的操作邏輯完全統(tǒng)一你不需要在insert/erase里寫一堆“if (head nullptr)”的特殊分支。我用三指針模型來(lái)理解這句話node* _M_head哨兵節(jié)點(diǎn)本身永遠(yuǎn)存在。_M_head-_M_next第一個(gè)有效節(jié)點(diǎn)空表時(shí)是nullptr。_M_head-_M_prev最后一個(gè)有效節(jié)點(diǎn)空表時(shí)是nullptr。實(shí)際存儲(chǔ)時(shí)還可以不單獨(dú)存_M_head指針而是讓哨兵節(jié)點(diǎn)作為list類的一個(gè)成員對(duì)象。不過(guò)為了代碼清晰后續(xù)示例統(tǒng)一用_M_node指針指向哨兵節(jié)點(diǎn)。我們還要讓list類同時(shí)持有allocator成員這樣節(jié)點(diǎn)分配和釋放都走分配器而不是直接new/delete——這是STL風(fēng)格的一個(gè)標(biāo)志容器不直接管理原始內(nèi)存它把內(nèi)存獲取和對(duì)象構(gòu)造解耦。模擬階段可以先簡(jiǎn)化但我建議一開始就寫上allocator模板參數(shù)省得以后想加還得改一堆簽名。template typename T, typename Alloc std::allocatorT class list { private: struct _Node { _Node* _M_prev; _Node* _M_next; T _M_data; explicit _Node(const T value) : _M_prev(nullptr), _M_next(nullptr), _M_data(value) {} explicit _Node(T value) : _M_prev(nullptr), _M_next(nullptr), _M_data(std::move(value)) {} }; using _NodeAlloc typename Alloc::template rebind_Node::other; using _NodePtr _Node*; using _DataAlloc Alloc; _NodePtr _M_node; // 哨兵節(jié)點(diǎn)指針 size_t _M_size; // 有效節(jié)點(diǎn)個(gè)數(shù) _NodeAlloc _M_node_alloc; public: using value_type T; using size_type size_t; using difference_type ptrdiff_t; using reference T; using const_reference const T; };rebind這個(gè)細(xì)節(jié)值得多說(shuō)一句。std::allocatorT本身分配的是T大小的內(nèi)存但鏈表節(jié)點(diǎn)是_Node包含指針和數(shù)據(jù)大小跟T不一定相同。STL規(guī)定allocator必須通過(guò)rebind_Node::other把分配器“轉(zhuǎn)綁”到節(jié)點(diǎn)類型上。雖然默認(rèn)分配器的rebind就是換個(gè)模板參數(shù)但自定義分配器如果不支持rebind標(biāo)準(zhǔn)容器就無(wú)法工作。我在自己實(shí)現(xiàn)時(shí)第一步就把_NodeAlloc類型別名寫好后面所有節(jié)點(diǎn)級(jí)內(nèi)存操作都從_M_node_alloc發(fā)起這樣才是真正的STL風(fēng)格而不是披著STL外衣的裸new鏈表。1.3 迭代器為什么必須封裝成類而不是裸指針這是list模擬實(shí)現(xiàn)最反直覺(jué)的一步。用慣了vector的人會(huì)覺(jué)得迭代器就是指針it就是地址加偏移但在list里這個(gè)想法直接崩掉。鏈表節(jié)點(diǎn)在內(nèi)存里是離散的node1并不是下一個(gè)節(jié)點(diǎn)所以迭代器如果要支持、--、*、-這些操作就必須保存“指向當(dāng)前節(jié)點(diǎn)的指針”然后讓運(yùn)算符重載來(lái)做“沿著next/prev移動(dòng)”這件事。也就是說(shuō)迭代器的數(shù)據(jù)成員就是一個(gè)_NodePtr而所有操作都是對(duì)指針的解引用和游走。還有一個(gè)比“能不能走”更隱蔽的問(wèn)題——空引用和類型安全。原生指針T*可以隨便指向任何地方也能隨便做算術(shù)壓根不知道“這是一次鏈表游走”。list的迭代器把游走規(guī)則封裝在operator里你永遠(yuǎn)不會(huì)寫出it it 3這種對(duì)鏈表毫無(wú)意義的代碼list迭代器是雙向迭代器只支持/--不支持隨機(jī)跳轉(zhuǎn)。封裝類還讓“const迭代器和非const迭代器”有了本質(zhì)區(qū)別而原生指針只能靠const T*來(lái)表達(dá)“數(shù)據(jù)只讀”無(wú)法表達(dá)“從某個(gè)節(jié)點(diǎn)開始只能向前走”。template typename T, typename Ref, typename Ptr struct _ListIterator { using iterator_category std::bidirectional_iterator_tag; using value_type T; using difference_type ptrdiff_t; using pointer Ptr; using reference Ref; _NodePtr _M_node; _ListIterator() noexcept : _M_node(nullptr) {} explicit _ListIterator(_NodePtr node) noexcept : _M_node(node) {} reference operator*() const noexcept { return _M_node-_M_data; } pointer operator-() const noexcept { return std::addressof(_M_node-_M_data); } _ListIterator operator() noexcept { _M_node _M_node-_M_next; return *this; } _ListIterator operator(int) noexcept { _ListIterator tmp(*this); (*this); return tmp; } _ListIterator operator--() noexcept { _M_node _M_node-_M_prev; return *this; } _ListIterator operator--(int) noexcept { _ListIterator tmp(*this); --(*this); return tmp; } friend bool operator(const _ListIterator a, const _ListIterator b) noexcept { return a._M_node b._M_node; } friend bool operator!(const _ListIterator a, const _ListIterator b) noexcept { return !(a b); } };注意到模板參數(shù)里有Ref和Ptr這是模仿gcc libstdc的經(jīng)典寫法。它讓一個(gè)類模板同時(shí)產(chǎn)出普通迭代器RefT, PtrT*和const迭代器Refconst T, Ptrconst T*不用寫兩份幾乎相同的代碼。這個(gè)設(shè)計(jì)我強(qiáng)烈建議保留因?yàn)楹竺鎸?shí)現(xiàn)insert、erase、splice這類接口時(shí)你會(huì)頻繁需要“用普通迭代器構(gòu)造const迭代器”的隱式轉(zhuǎn)換一對(duì)模板參數(shù)搞定。2. 迭代器實(shí)現(xiàn)與STL迭代器規(guī)范2.1 iterator_traits讓算法知道迭代器的類型很多自學(xué)C的人會(huì)在這一步卡殼明明自己寫的list里也有iterator類型為什么std::reverse、std::distance、std::next這些標(biāo)準(zhǔn)庫(kù)算法就是不肯配合原因是標(biāo)準(zhǔn)算法不直接認(rèn)“你這個(gè)類叫iterator”而是通過(guò)std::iterator_traitsIter去取迭代器的五件套iterator_category、value_type、difference_type、pointer、reference。只要你的迭代器類內(nèi)部定義了這些嵌套類型iterator_traits就有默認(rèn)的特化路徑能拿到它們。不過(guò)這里有個(gè)坑如果你在list類內(nèi)部寫了一個(gè)嵌套的iterator結(jié)構(gòu)std::iterator_traits仍然會(huì)正常工作嗎答案是會(huì)的C標(biāo)準(zhǔn)規(guī)定std::iterator_traitsIter的主模板就是直接取Iter::iterator_category這類成員類型前提是這些成員存在。但如果你的迭代器是const T*這種原生指針就必須靠偏特化std::iterator_traitsT*來(lái)補(bǔ)充定義。我建議在寫list之前先做個(gè)快速驗(yàn)證把下面這段丟進(jìn)編譯器看看std::distance能不能在你的迭代器上工作static_assert(std::is_same_v std::iterator_traits_ListIteratorT, T, T*::iterator_category, std::bidirectional_iterator_tag); static_assert(std::is_same_v std::iterator_traits_ListIteratorT, T, T*::value_type, T);如果編譯過(guò)了說(shuō)明迭代器的“身份證”齊了。iterator_category尤其重要它決定了算法如何選擇重載。比如std::advance(it, n)在面對(duì)random_access_iterator_tag時(shí)可以直接it n而面對(duì)bidirectional_iterator_tag只能老老實(shí)實(shí)/--循環(huán)。list的迭代器是雙向迭代器所以這里必須寫std::bidirectional_iterator_tag寫錯(cuò)了或者不寫某些算法會(huì)直接編譯失敗或者退化成無(wú)意義的死循環(huán)。2.2 const迭代器與隱式轉(zhuǎn)換讀寫權(quán)限的邊界list類里通常會(huì)這樣定義迭代器別名using iterator _ListIteratorT, T, T*; using const_iterator _ListIteratorT, const T, const T*; using reverse_iterator std::reverse_iteratoriterator; using const_reverse_iterator std::reverse_iteratorconst_iterator;std::reverse_iterator是一個(gè)適配器你只需要給它一個(gè)雙向迭代器它自動(dòng)把變成--、--變成這讓list不用為反向遍歷寫出另一套底層結(jié)構(gòu)。但問(wèn)題來(lái)了容器類型listT和listconst T是完全不同的類型你不能簡(jiǎn)單靠類模板的const來(lái)獲得const迭代器。所以容器內(nèi)部必須提供iterator begin()和const_iterator begin() const這樣的重載對(duì)并且要支持iterator到const_iterator的隱式轉(zhuǎn)換。這就是我們把迭代器寫成模板的好處——給_ListIterator加一個(gè)轉(zhuǎn)換構(gòu)造函數(shù)template typename _Tp, typename _Ref, typename _Ptr struct _ListIterator { // 前面的成員不變... // 允許普通迭代器轉(zhuǎn)換為const迭代器但不允許反向轉(zhuǎn)換 template typename _Ref2, typename _Ptr2, typename std::enable_if_t std::is_convertible_v_Ref2, Ref std::is_convertible_v_Ptr2, Ptr _ListIterator(const _ListIteratorT, _Ref2, _Ptr2 other) noexcept : _M_node(other._M_node) {} };這個(gè)轉(zhuǎn)換構(gòu)造函數(shù)相當(dāng)克制它只允許“讀權(quán)限擴(kuò)大”的轉(zhuǎn)換也就是iterator - const_iteratorconst_iterator - iterator因?yàn)閏onst T無(wú)法轉(zhuǎn)換成T會(huì)被enable_if攔下。這一步做對(duì)了才不會(huì)出現(xiàn)你返回一個(gè)const迭代器、外部卻拿來(lái)修改數(shù)據(jù)的漏洞。很多初學(xué)者仿照網(wǎng)上簡(jiǎn)化版list寫出的代碼到這里都是直接不寫轉(zhuǎn)換構(gòu)造導(dǎo)致list.begin()和容器的const成員函數(shù)接口配對(duì)失敗編譯報(bào)出一大堆看不懂的模板報(bào)錯(cuò)。這里我踩過(guò)最痛的坑是沒(méi)有給迭代器加noexcept。別小看這個(gè)標(biāo)準(zhǔn)容器要求迭代器拷貝、移動(dòng)、比較這些操作不得拋異常因?yàn)楹芏喾盒退惴〞?huì)基于noexcept來(lái)選不同的移動(dòng)策略。如果你的迭代器寫成了可能拋異常的拷貝構(gòu)造std::list::erase在刪除一批元素時(shí)可能就不再走高效的節(jié)點(diǎn)回收路徑了。2.3 迭代器與節(jié)點(diǎn)互換為什么insert需要私有構(gòu)造在實(shí)現(xiàn)insert和erase時(shí)需要把“迭代器”和“節(jié)點(diǎn)指針”相互轉(zhuǎn)換。迭代器看到的是一個(gè)封裝好的類它的_M_node成員是私有的外部無(wú)法直接拿到裸指針去拼新節(jié)點(diǎn)。一個(gè)常見的做法是在list類的內(nèi)部實(shí)現(xiàn)里再創(chuàng)建一個(gè)“裸構(gòu)造”的迭代器像這樣private: // 僅用于內(nèi)部構(gòu)造迭代器外部不可見 static iterator _S_make_iterator(_NodePtr p) noexcept { return iterator(p); }因?yàn)閕terator只有一個(gè)帶_NodePtr參數(shù)的構(gòu)造函數(shù)而這個(gè)構(gòu)造函數(shù)如果寫成public外部就能隨便把一個(gè)節(jié)點(diǎn)指針偽裝成迭代器破壞了封裝。所以我會(huì)把這個(gè)構(gòu)造函數(shù)放在private區(qū)然后在list類的成員函數(shù)里通過(guò)friend或內(nèi)部工具函數(shù)使用。std::list現(xiàn)代實(shí)現(xiàn)也是這個(gè)套路iterator類本身會(huì)聲明容器類為friend保證“只有容器才能從節(jié)點(diǎn)指針安全構(gòu)造迭代器”。有了這個(gè)能力insert才能寫出“返回指向新插入元素的迭代器”的語(yǔ)義。C標(biāo)準(zhǔn)規(guī)定list::insert()的返回值是插入后新元素的迭代器vector的insert則返回插入位置的迭代器二者不同。如果不小心把語(yǔ)義寫錯(cuò)外部算法表現(xiàn)會(huì)非常奇怪比如連續(xù)insert時(shí)新迭代器總是指向舊元素。3. 構(gòu)造函數(shù)家族與內(nèi)存管理3.1 構(gòu)造函數(shù)的五大金剛默認(rèn)、填充、范圍、拷貝、移動(dòng)list的構(gòu)造函數(shù)數(shù)量比一般人想的多。除了默認(rèn)構(gòu)造STL還要求支持list(size_type n)、list(size_type n, const T value)、list(InputIt first, InputIt last)以及C11后的initializer_listT。模擬實(shí)現(xiàn)時(shí)不必每一個(gè)都寫字字珠璣的實(shí)現(xiàn)但必須明白它們共用同一條內(nèi)部通道——_M_insert。以一個(gè)通用填充實(shí)現(xiàn)為例內(nèi)部關(guān)鍵是一段讓新手最容易頭暈的代碼也就是“邊申請(qǐng)節(jié)點(diǎn)邊插入任何一步拋異常都要回滾”。我不建議一上來(lái)就寫異常安全滿分版本先寫出能跑的版本再逐步加強(qiáng)。初級(jí)版本可以這樣組織template typename InputIt list(InputIt first, InputIt last, typename std::enable_if!std::is_integral_vInputIt::type* nullptr) { _M_init(); for (; first ! last; first) emplace_back(*first); }為什么要enable_if因?yàn)閘ist(size_type n)接收到整數(shù)參數(shù)時(shí)如果不做區(qū)分范圍構(gòu)造函數(shù)會(huì)跟整數(shù)版本產(chǎn)生重載歧義listint l(10, 20)到底是10個(gè)默認(rèn)值還是從迭代器范圍構(gòu)造標(biāo)準(zhǔn)庫(kù)靠iterator_traits區(qū)分我們模擬時(shí)用is_integral攔截就夠了。這也是熱詞里反復(fù)出現(xiàn)“構(gòu)造”、“拷貝構(gòu)造函數(shù)調(diào)用時(shí)機(jī)”背后的一個(gè)考點(diǎn)——構(gòu)造函數(shù)家族不僅講究“能編”還講究“重載決議不出歧義”。_M_init用來(lái)初始化哨兵節(jié)點(diǎn)并置零sizevoid _M_init() { _M_node _M_alloc_node(); // 分配一個(gè)哨兵節(jié)點(diǎn) _M_node-_M_next nullptr; _M_node-_M_prev nullptr; _M_size 0; }多啰嗦一句很多人的第一版list習(xí)慣用“空鏈表頭指針為nullptr”結(jié)果insert、erase、遍歷到處都要判空寫起來(lái)非常累。而哨兵模式下一勞永逸遍歷的終點(diǎn)就是哨兵本身begin()是_M_node-_M_nextend()是_M_node天然閉合成環(huán)。這個(gè)設(shè)計(jì)在STL里已經(jīng)用了二十年是經(jīng)過(guò)實(shí)戰(zhàn)檢驗(yàn)的不要為了“少一個(gè)節(jié)點(diǎn)”而放棄它。3.2 allocator與節(jié)點(diǎn)的構(gòu)造/析構(gòu)誰(shuí)負(fù)責(zé)內(nèi)存誰(shuí)負(fù)責(zé)生命直接new一個(gè)節(jié)點(diǎn)不就行了嗎為什么還要allocator如果你只是為了寫出“一個(gè)能跑的list”那確實(shí)可以new/delete但你定義的是listT, Alloc的模板就必須考慮分配器是外部注入的類型。比如用戶可能傳入一個(gè)池化分配器希望所有節(jié)點(diǎn)從預(yù)先分配的內(nèi)存池里取。此外標(biāo)準(zhǔn)容器對(duì)異常安全有明確要求構(gòu)造元素時(shí)拋異常內(nèi)存不能泄漏銷毀元素時(shí)節(jié)點(diǎn)內(nèi)存要正確返還給分配器而不是簡(jiǎn)單delete。我習(xí)慣把節(jié)點(diǎn)內(nèi)存和對(duì)象生命周期拆成四個(gè)函數(shù)_NodePtr _M_alloc_node() { return _M_node_alloc.allocate(1); } template typename... Args _NodePtr _M_construct_node(Args... args) { _NodePtr p _M_alloc_node(); try { // 在已分配內(nèi)存上構(gòu)造節(jié)點(diǎn)而不是new p(args...) std::allocator_traits_NodeAlloc::construct( _M_node_alloc, p, std::forwardArgs(args)...); } catch (...) { _M_node_alloc.deallocate(p, 1); throw; } return p; } void _M_destroy_node(_NodePtr p) noexcept { std::allocator_traits_NodeAlloc::destroy(_M_node_alloc, p); _M_node_alloc.deallocate(p, 1); }關(guān)鍵在于construct、destroy這兩個(gè)allocator_traits接口。std::allocator_traits是一層“默認(rèn)實(shí)現(xiàn)”的殼如果你自定義的分配器沒(méi)提供construct它會(huì)退回到::new((void*)p) T(args...)如果提供了就用自定義版本。調(diào)用方統(tǒng)一走allocator_traits容器代碼就不需要判斷分配器到底支不支持自定義構(gòu)造。這也是STL源碼一眼望去全是allocator_traits的原因。我在模擬實(shí)現(xiàn)早期偷懶直接用了new (p) _Node(value)寫起來(lái)很快但一旦把分配器換成帶統(tǒng)計(jì)功能的測(cè)試分配器就會(huì)發(fā)現(xiàn)問(wèn)題內(nèi)存計(jì)數(shù)對(duì)不上因?yàn)槔@過(guò)分配器的construct那一步。后來(lái)全部改成allocator_traits風(fēng)格內(nèi)存全程由分配器記賬調(diào)試自定義分配器時(shí)輕松很多。3.3 拷貝構(gòu)造的深拷貝實(shí)現(xiàn)異常安全是關(guān)鍵拷貝構(gòu)造是最能暴露鏈表功力的地方。你不能只拷貝頭指針那樣兩個(gè)list會(huì)共享同一串節(jié)點(diǎn)析構(gòu)時(shí)雙重釋放直接崩潰。深拷貝的常規(guī)做法是遍歷源鏈表依次尾插新節(jié)點(diǎn)但這個(gè)樸素寫法有一個(gè)致命問(wèn)題——如果中途拋異常比如T的拷貝構(gòu)造拋了已經(jīng)插進(jìn)去的節(jié)點(diǎn)就泄漏了。我推薦寫成“構(gòu)造一個(gè)新哨兵 異常時(shí)整體清理”的結(jié)構(gòu)list(const list other) { _M_init(); try { for (const_iterator it other.begin(); it ! other.end(); it) emplace_back(*it); } catch (...) { clear(); _M_dealloc_node(_M_node); _M_node nullptr; throw; } }這樣一旦中途失敗析構(gòu)入口還能看到有效對(duì)象狀態(tài)。不過(guò)在更學(xué)院派的實(shí)現(xiàn)里會(huì)用帶next指針的“半成品鏈表構(gòu)建器”構(gòu)造到一半再整體掛接那是為了追求強(qiáng)異常保證。模擬實(shí)現(xiàn)先保證“不泄漏”已經(jīng)夠及格有興趣可以繼續(xù)優(yōu)化到“copy期間源被修改不會(huì)影響當(dāng)前操作”。寫完拷貝構(gòu)造后順手做一份測(cè)試定義兩個(gè)list互相拷貝然后修改其中一個(gè)另一個(gè)必須完全不受影響同時(shí)二者各自的end()、begin()迭代器不能交叉指向?qū)Ψ降墓?jié)點(diǎn)。這個(gè)測(cè)試不過(guò)關(guān)多半是拷貝構(gòu)造里不小心共享了哨兵節(jié)點(diǎn)。3.4 拷貝賦值與copy-and-swap最穩(wěn)的賦值寫法拷貝賦值有兩條路線。一條是傳統(tǒng)的“先clear再逐個(gè)插入”它的問(wèn)題是如果插入中途拋異常當(dāng)前對(duì)象已經(jīng)被清空了處于“半空半新”的損壞狀態(tài)不滿足強(qiáng)異常安全。另一條是copy-and-swap先用拷貝構(gòu)造生成一個(gè)臨時(shí)list然后交換臨時(shí)list和當(dāng)前對(duì)象的內(nèi)容臨時(shí)對(duì)象析構(gòu)時(shí)帶走舊數(shù)據(jù)。實(shí)現(xiàn)swap時(shí)注意只需要交換三個(gè)東西哨兵指針、size、allocator。allocator比較麻煩C11后規(guī)定“分配器相等時(shí)容器可以交換”我們模擬階段先假定所有std::allocator都是相等的直接交換即可如果對(duì)象和臨時(shí)對(duì)象分配器不相等標(biāo)準(zhǔn)做法是逐節(jié)點(diǎn)搬移這個(gè)屬于進(jìn)階討論初學(xué)階段可以忽略。list operator(const list other) { if (this ! other) { list tmp(other); // 深拷貝 swap(tmp); // 交換所有成員 } // tmp析構(gòu)釋放舊數(shù)據(jù) return *this; }這個(gè)寫法用三個(gè)“標(biāo)準(zhǔn)動(dòng)作”就完成了強(qiáng)異常保證要么賦值成功要么當(dāng)前對(duì)象保持原值。很多人一開始不敢用copy-and-swap怕“拷貝整個(gè)鏈表太浪費(fèi)”。實(shí)際場(chǎng)景下大多數(shù)賦值操作本來(lái)就需要完整的深拷貝語(yǔ)義暫時(shí)無(wú)法復(fù)用舊節(jié)點(diǎn)寫起來(lái)省心比省幾次拷貝更重要。如果你真在乎性能后續(xù)再優(yōu)化成“盡量復(fù)用已有節(jié)點(diǎn)”的版本但那些版本要處理的邊界非常多不建議作為第一版實(shí)現(xiàn)。移動(dòng)構(gòu)造和移動(dòng)賦值則簡(jiǎn)單很多。移動(dòng)構(gòu)造只要把源對(duì)象的哨兵指針收過(guò)來(lái)然后把源對(duì)象置為空表移動(dòng)賦值也走swap或者先swap再讓源對(duì)象持有舊數(shù)據(jù)收尾。list(list other) noexcept : _M_node(other._M_node), _M_size(other._M_size), _M_node_alloc(std::move(other._M_node_alloc)) { other._M_node nullptr; other._M_size 0; } list operator(list other) noexcept { if (this ! other) { clear(); _M_dealloc_node(_M_node); _M_node other._M_node; _M_size other._M_size; other._M_node nullptr; other._M_size 0; } return *this; }移動(dòng)構(gòu)造里有個(gè)小細(xì)節(jié)源對(duì)象置空后哨兵節(jié)點(diǎn)也沒(méi)了因此源對(duì)象的析構(gòu)函數(shù)必須支持_M_node nullptr。標(biāo)準(zhǔn)庫(kù)的實(shí)現(xiàn)里被移動(dòng)后的標(biāo)準(zhǔn)容器“有效但未指定狀態(tài)”允許為空表。我自己寫析構(gòu)時(shí)一定會(huì)加這個(gè)判斷~list() { if (_M_node) { clear(); _M_dealloc_node(_M_node); _M_node nullptr; } }4. 實(shí)操核心操作實(shí)現(xiàn)與調(diào)試實(shí)錄4.1 插入與刪除統(tǒng)一走_(dá)M_insert、_M_erase兩條內(nèi)部通道先把外界最常調(diào)的接口列出來(lái)然后看它們?nèi)绾问諗康絻蓚€(gè)內(nèi)部函數(shù)。push_front等價(jià)于在begin()處插入push_back等價(jià)于在end()處插入insert(it, value)的返回值是新元素迭代器erase(it)的返回值是被刪元素的下一個(gè)元素的迭代器。注意list的erase返回的是下一個(gè)有效迭代器不是void這點(diǎn)和vector一致但是list的erase不會(huì)讓其他迭代器失效因?yàn)閯h除節(jié)點(diǎn)只動(dòng)了局部指針。內(nèi)部實(shí)現(xiàn)我統(tǒng)一這樣寫iterator _M_insert(const_iterator position, const T value) { _NodePtr new_node _M_construct_node(value); _NodePtr pos position._M_node; new_node-_M_next pos; new_node-_M_prev pos-_M_prev; if (pos-_M_prev) pos-_M_prev-_M_next new_node; pos-_M_prev new_node; _M_size; return iterator(new_node); } iterator _M_erase(const_iterator position) { _NodePtr pos position._M_node; _NodePtr prev pos-_M_prev; _NodePtr next pos-_M_next; if (prev) prev-_M_next next; if (next) next-_M_prev prev; --_M_size; _M_destroy_node(pos); return iterator(next); }由于有哨兵節(jié)點(diǎn)的存在pos-_M_prev和pos-_M_next理論上都不會(huì)是nullptr除非你允許迭代器指向哨兵本身即end()所以很多實(shí)現(xiàn)直接省略空判斷。不過(guò)我在調(diào)試階段踩過(guò)“空鏈表上調(diào)用erase(end())”的坑標(biāo)準(zhǔn)庫(kù)里這是未定義行為但調(diào)試版四種標(biāo)準(zhǔn)庫(kù)都有斷言我自己實(shí)現(xiàn)寧可保留判空邏輯讓錯(cuò)誤提前暴露雖然在release版下會(huì)多幾條分支判斷體感無(wú)差別。emplace_back是push_back的進(jìn)階版它把參數(shù)包直接轉(zhuǎn)發(fā)給_M_construct_node在節(jié)點(diǎn)內(nèi)存上直接構(gòu)造T而不是先構(gòu)造T再拷貝進(jìn)節(jié)點(diǎn)。這一步省掉一次移動(dòng)/拷貝是“STL風(fēng)格編程”里很標(biāo)志性的寫法。下面的代碼同時(shí)處理了參數(shù)的完美轉(zhuǎn)發(fā)template typename... Args void emplace_back(Args... args) { _NodePtr new_node _M_construct_node(std::forwardArgs(args)...); _NodePtr tail _M_node-_M_prev; if (tail) { tail-_M_next new_node; new_node-_M_prev tail; } else { _M_node-_M_next new_node; new_node-_M_prev _M_node; } new_node-_M_next _M_node; _M_node-_M_prev new_node; _M_size; }4.2 完整代碼組織頭文件結(jié)構(gòu)、namespace與內(nèi)聯(lián)模擬實(shí)現(xiàn)建議把代碼放在頭文件里全部聲明為inline或者直接定義在類內(nèi)。不要試圖做list.h聲明加list.cpp定義分離模板類分離編譯會(huì)帶來(lái)一堆鏈接錯(cuò)誤熱詞里“c#調(diào)用c出現(xiàn)access violation c0000005”、“vscode配置c/c環(huán)境”這類問(wèn)題很多根源就是模板的聲明與定義分離。C模板只有在實(shí)例化時(shí)才知道具體類型編譯器必須在每個(gè)翻譯單元都能看到完整實(shí)現(xiàn)否則只能換來(lái)一個(gè)“undefined reference”。通常的做法是建一個(gè)mylist命名空間避免污染全局命名空間。頭文件開頭寫好包含保護(hù)或#pragma once然后按順序組織節(jié)點(diǎn)結(jié)構(gòu) - 迭代器結(jié)構(gòu) - list類框架 - 成員函數(shù)實(shí)現(xiàn)。這種組織方式跟你自己去翻bits/stl_list.h看到的源碼順序幾乎一致對(duì)著看的時(shí)候會(huì)覺(jué)得非常親切。我還會(huì)加一組static_assert來(lái)驗(yàn)證迭代器類型和容器類型別名這比編譯運(yùn)行后再手動(dòng)驗(yàn)證要省事得多。#pragma once #include memory #include iterator #include algorithm #include utility #include type_traits namespace mylist { // 節(jié)點(diǎn)、迭代器、list 的實(shí)現(xiàn)... } // namespace mylistnamespace是一個(gè)細(xì)節(jié)點(diǎn)標(biāo)準(zhǔn)庫(kù)的std::list也在namespacestd內(nèi)部外部代碼靠using聲明或者std::前綴訪問(wèn)。我們自己實(shí)現(xiàn)放獨(dú)立namespace能避免和標(biāo)準(zhǔn)庫(kù)的std::list沖突同時(shí)還能在同一個(gè)測(cè)試文件里同時(shí)includelist和mylist.h直接對(duì)比行為差異。4.3 測(cè)試驅(qū)動(dòng)遍歷、插入刪除、迭代器有效性完整代碼寫完只是開始測(cè)試才是真正見真章的地方。我通常先跑四組用例每一組都奔著某個(gè)特定崩潰點(diǎn)去第一組空表操作??誰(shuí)ist的begin()end()應(yīng)該為真size()0push_front和push_back各插一個(gè)后size()2此時(shí)打斷點(diǎn)觀察哨兵節(jié)點(diǎn)的prev和next是否正確。第二組普通插入和刪除。插入10個(gè)元素用迭代器隔一個(gè)刪一個(gè)驗(yàn)證每次erase返回的迭代器能繼續(xù)安全。這是很多簡(jiǎn)化版list過(guò)不去的坎原因往往是erase返回的迭代器指向了已經(jīng)被destroy的節(jié)點(diǎn)然后下一輪訪問(wèn)野指針。第三組迭代器失效檢查。關(guān)鍵測(cè)試是保存一個(gè)指向第3個(gè)元素的迭代器然后push_back一個(gè)元素再訪問(wèn)舊迭代器它必須還能正常解引用。這個(gè)特性是list族容器最值錢的承諾如果你是用“vector式的整塊搬移”思路寫鏈表這段話多半會(huì)翻車。第四組大容量構(gòu)造與析構(gòu)。創(chuàng)建10萬(wàn)個(gè)元素反復(fù)拷貝賦值和移動(dòng)賦值用系統(tǒng)自帶的任務(wù)管理器觀察內(nèi)存有沒(méi)有只漲不降。這一步能抓出析構(gòu)里漏掉的節(jié)點(diǎn)回收、拷貝賦值中未釋放的舊數(shù)據(jù)。我這里貼一個(gè)比較常用的測(cè)試?yán)铀瑫r(shí)覆蓋了“遍歷寫、遍歷刪、反向遍歷”#include cassert #include iostream #include mylist.h int main() { mylist::listint nums; for (int i 0; i 10; i) nums.emplace_back(i); // 正向遍歷把偶數(shù)項(xiàng)刪掉 for (auto it nums.begin(); it ! nums.end();) { if (*it % 2 0) it nums.erase(it); else it; } // 反向遍歷打印奇數(shù)項(xiàng) for (auto it nums.rbegin(); it ! nums.rend(); it) std::cout *it ; std::cout \n; // 驗(yàn)證size和內(nèi)容 assert(nums.size() 5); int expect 1; for (auto x : nums) { assert(x expect); expect 2; } std::cout all tests passed std::endl; }這個(gè)程序里最值得注意的寫法是用it nums.erase(it)而不是刪完再it。在list里erase后當(dāng)前迭代器已經(jīng)失效直接it就是訪問(wèn)被釋放內(nèi)存這一步在release版可能僥幸不崩在debug版必然觸發(fā)斷言或者得到隨機(jī)值。你去看各種C面試題十有八九會(huì)考這一點(diǎn)。5. 常見問(wèn)題與排查技巧實(shí)錄5.1 迭代器失效與野指針為什么erase后不能再用舊迭代器模擬實(shí)現(xiàn)list遇到的最多的錯(cuò)誤就是刪除節(jié)點(diǎn)后繼續(xù)使用指向該節(jié)點(diǎn)的迭代器。比如for (auto it list.begin(); it ! list.end(); it) { if (*it 3) list.erase(it); // 錯(cuò)誤erase后it已經(jīng)失效 }在list里erase(it)已經(jīng)destroy了迭代器指向的節(jié)點(diǎn)并釋放了內(nèi)存后續(xù)對(duì)it的、*it都是懸垂訪問(wèn)輕則讀到臟數(shù)據(jù)重則直接段錯(cuò)誤。正確姿勢(shì)是讓迭代器“先走一步再刪”或者直接接收erase的返回值// 方法一先保存后繼 auto next_it std::next(it); list.erase(it); it next_it; // 方法二直接使用返回值推薦最簡(jiǎn)潔 it list.erase(it);另外一個(gè)常見的隱藏問(wèn)題不要在遍歷過(guò)程中const引用和普通迭代器混用。一個(gè)const迭代器和普通迭代器同時(shí)指向同一個(gè)節(jié)點(diǎn)刪除后再解引用const迭代器同樣會(huì)觸發(fā)spectre般的未定義行為。list能保證的是“其他未刪除節(jié)點(diǎn)的迭代器依舊有效”這已經(jīng)是性價(jià)比極高的承諾。5.2 訪問(wèn)沖突c0000005與破壞的鏈表結(jié)構(gòu)熱詞里有“c#調(diào)用c出現(xiàn)access violation c0000005”這是Windows下C調(diào)用方最常見的崩潰之一對(duì)應(yīng)Linux上的segmentation fault。放在list場(chǎng)景里絕大部分原因是鏈表指針斷鏈后的解引用。比如insert在空表時(shí)如果忘記掛接哨兵節(jié)點(diǎn)的next/prev之后訪問(wèn)_M_node-_M_next-_M_next就會(huì)讀到非法地址。我自己排過(guò)很多次這種問(wèn)題最有效的調(diào)試武器就是“內(nèi)存斷點(diǎn)”。所謂內(nèi)存斷點(diǎn)是在調(diào)試器里對(duì)一個(gè)節(jié)點(diǎn)的地址設(shè)置寫入斷點(diǎn)比如你要檢查節(jié)點(diǎn)A的_M_next什么時(shí)候被改壞就給A-_M_next下斷點(diǎn)。此時(shí)任何一段代碼試圖改寫這個(gè)地址都會(huì)立刻斷下來(lái)你就能看到是insert還是erase寫錯(cuò)了順序。這個(gè)方法在Windows的Visual Studio和Linux的gdb里都支持gdb里的命令是watch *((long*)node-next)。這里再分享一個(gè)我經(jīng)常用到的鏈表完整性校驗(yàn)函數(shù)。把它掛在每次操作后跑一遍能在問(wèn)題擴(kuò)大之前抓住指針斷鏈void _M_check_linkage() const { if (_M_size 0) { assert(_M_node-_M_next nullptr || _M_node-_M_next nullptr); assert(_M_node-_M_prev nullptr || _M_node-_M_prev nullptr); } else { _NodePtr p _M_node-_M_next; size_t count 0; while (p ! _M_node) { count; assert(p-_M_next ! nullptr); assert(p-_M_next-_M_prev p); p p-_M_next; } assert(count _M_size); assert(_M_node-_M_prev p-_M_prev); } }這個(gè)函數(shù)檢查的是“雙向一致性”任意節(jié)點(diǎn)的next所指節(jié)點(diǎn)的prev必須指回自己。大多數(shù)鏈表崩潰追根究底都是這一步被破壞寫錯(cuò)了insert的“先掛prev再改prev的next”就會(huì)導(dǎo)致回程遍歷時(shí)指針跳飛。5.3 構(gòu)造與析構(gòu)不匹配內(nèi)存泄漏、double-free熱詞里“拷貝構(gòu)造函數(shù)調(diào)用時(shí)機(jī)”和“microsoft visual c redistributable”同時(shí)出現(xiàn)我猜測(cè)提問(wèn)者很可能是在Windows上調(diào)試時(shí)遇到分配器或CRT報(bào)錯(cuò)。這里要區(qū)分兩個(gè)層面如果用的是std::allocator構(gòu)造和析構(gòu)只要嚴(yán)格配對(duì)不會(huì)有問(wèn)題但如果你為了練手寫了自定義分配器那么最容易犯的錯(cuò)就是“用allocate分配卻用delete釋放”或者反過(guò)來(lái)。allocate和deallocate必須一對(duì)一construct和destroy必須一對(duì)一這兩對(duì)之間不能交叉。很多自定義分配器在里頭記錄了一個(gè)“已分配塊列表”交叉調(diào)用會(huì)導(dǎo)致斷言崩潰。檢查清單如下每個(gè)節(jié)點(diǎn)分配對(duì)應(yīng)一次節(jié)點(diǎn)銷毀和一次deallocate。銷毀哨兵節(jié)點(diǎn)時(shí)也要先destroy哨兵里的數(shù)據(jù)雖然沒(méi)有有效數(shù)據(jù)但標(biāo)準(zhǔn)庫(kù)的實(shí)現(xiàn)會(huì)把哨兵的data視為已構(gòu)造必須destroy再deallocate??截愘x值時(shí)先釋放舊數(shù)據(jù)再裝新數(shù)據(jù)順序反了會(huì)double-free。我在調(diào)試時(shí)還會(huì)把_M_size和實(shí)際遍歷節(jié)點(diǎn)數(shù)比對(duì)數(shù)值不一致說(shuō)明有節(jié)點(diǎn)泄漏或重復(fù)釋放。搭配valgrindLinux或者Visual Studio的診斷模式Windows跑一遍測(cè)試用例通常能在五分鐘內(nèi)定位到問(wèn)題。如果工具暫時(shí)沒(méi)法用那就退回到“_M_check_linkage 內(nèi)存斷點(diǎn)”這條純手工路線。5.4 編譯報(bào)錯(cuò)的排除思路模板報(bào)錯(cuò)為什么又臭又長(zhǎng)手寫模板容器最勸退人的地方就是編譯報(bào)錯(cuò)。刪除一個(gè)節(jié)點(diǎn)時(shí)報(bào)錯(cuò)信息能刷出一整屏的模板實(shí)例化上下文看著跟天書一樣。我的經(jīng)驗(yàn)是分三步走。第一步先看報(bào)錯(cuò)第一行和最后一行通常是“required from here”它會(huì)告訴你這次實(shí)例化是從哪句調(diào)用發(fā)起的。絕大多數(shù)情況下問(wèn)題出現(xiàn)在你調(diào)用容器的那個(gè)函數(shù)里而不是容器實(shí)現(xiàn)內(nèi)部。第二步把那些很奇怪的長(zhǎng)類型名折疊掉。使用別名、using聲明、或者直接用auto接收返回值能顯著減少閱讀負(fù)擔(dān)。比如auto it nums.begin();而不是mylist::listint::iterator it nums.begin();。第三步用“最小復(fù)現(xiàn)”的方式把報(bào)錯(cuò)縮小。比如單獨(dú)寫一行nums.erase(nums.begin());如果編譯不過(guò)再縮小到nums.begin()和nums.erase各自的類型約束上。我遇到的大部分模板編譯失敗最終都落在“迭代器的value_type和容器的value_type不匹配”上比如把const_iterator傳給了需要iterator的重載。這時(shí)回頭檢查你的const轉(zhuǎn)換構(gòu)造函數(shù)是否寫了enable_if十有八九就是它在攔路。開發(fā)環(huán)境建議統(tǒng)一用近幾年的編譯器和標(biāo)準(zhǔn)。評(píng)論區(qū)經(jīng)常有人拿老式Visual Studio 2015編譯一堆C11時(shí)代的例子失敗這并不代表代碼有問(wèn)題而是老編譯器對(duì)模板的支持不完整。項(xiàng)目里熱詞反復(fù)出現(xiàn)“vscode配置c/c環(huán)境”說(shuō)明很多人在編輯器層面就卡住了。這里給個(gè)不出錯(cuò)的最小配置思路裝好編譯器后在vscode里配置tasks.json的編譯命令加-Wall -Wextra -g再配上c_cpp_properties.json里的cppStandard為c17就夠跑本文所有代碼了。不需要裝一堆花哨擴(kuò)展。6. 從模擬到實(shí)戰(zhàn)list之后還能擴(kuò)展什么做完這個(gè)list模擬實(shí)現(xiàn)其實(shí)已經(jīng)把STL容器設(shè)計(jì)里最硬核的牙齒啃下來(lái)了。后面可以順手做幾件很好玩的事給list加上std::initializer_list構(gòu)造讓{1,2,3}這種語(yǔ)法直接可用實(shí)現(xiàn)splice接口用O(1)時(shí)間把另一個(gè)list的一段節(jié)點(diǎn)搬過(guò)來(lái)寫一個(gè)簡(jiǎn)單的std::hash特化讓list可以作為unordered_map的value。再往后可以試試用同樣的迭代器封裝思路去寫一個(gè)unordered_map的bucket單向鏈表迭代器那種“跳到下一個(gè)桶”的感覺(jué)本質(zhì)上跟list的“跳到下一個(gè)節(jié)點(diǎn)”是一樣的。我個(gè)人更推薦的下一個(gè)實(shí)練項(xiàng)目是手寫vectorchar的迭代器因?yàn)樗茏屇泱w會(huì)“隨機(jī)訪問(wèn)迭代器和雙向迭代器”的實(shí)現(xiàn)差異。操作起來(lái)會(huì)比list的迭代器簡(jiǎn)單不少但正因?yàn)楹?jiǎn)單你會(huì)發(fā)現(xiàn)必要時(shí)還要處理“迭代器失效”之外的“容量增長(zhǎng)時(shí)所有迭代器全部失效”的問(wèn)題。兩相對(duì)比才真正理解為什么標(biāo)準(zhǔn)庫(kù)里list和vector的迭代器承諾完全不同。很多人在這一步豁然開朗原來(lái)之前糾結(jié)的“為什么vector插入會(huì)失效、list不會(huì)”根本不是玄學(xué)而是數(shù)據(jù)結(jié)構(gòu)物理形態(tài)決定的必然結(jié)果。如果還想繼續(xù)深化“STL風(fēng)格編程”建議去讀libstdc的bits/stl_list.h源碼重點(diǎn)看兩個(gè)點(diǎn)一是_List_node_base這個(gè)基類如何用繼承來(lái)減輕模板膨脹二是_List_const_iterator和_List_iterator之間如何用宏或者模板參數(shù)復(fù)用實(shí)現(xiàn)。看的時(shí)候拿自己寫的代碼對(duì)照會(huì)發(fā)現(xiàn)你的版本和標(biāo)準(zhǔn)庫(kù)的版本相差的只是工程優(yōu)化核心骨架完全一致。這種“原來(lái)我寫的思路跟大師差不多”的時(shí)刻是我覺(jué)得手寫STL容器最能帶來(lái)成就感的地方。
返回列表
PREV
查看更多資訊
NEXT
返回資訊列表
丝袜美腿操av| 亚洲脚交| 色婷婷九月天天综合| 香港久久久| 后入内射蜜桃臀| 國產尤物AV尤物在線觀看 | 91视频伊人| 东京热不卡视频| 国产99 中文字幕日韩小视频| 伊香蕉综合久久久久久久噜噜噜 | 超碰色老头| 久久久久久裸体| 综合网,亚洲,欧美| 静品嫩模一区二区| 伦伦成年午夜免费视频| 免费A片三p视频| 青草一区二区| 亚洲综合影院| 欧美人人曰人人操人人射射| 成人26uuu| 婷婷超| 欧洲自拍色图gif在线| 日本一本一区二区三区四区五区欧美日韩中文字幕| 999亚洲国产视频| 中文字幕国产在线天堂| 午夜国产综合视频在线观看| 亚洲男人天堂手机版| 日本中文字幕一区| 9长久久精品| 日韩在线97| 日欧美色| 色女99一级片在线观看| 久久啊哟| yazhousetuoumei| 99精品久久| 亚洲精品一区二区三区在线播放| 国产一区在线观看无码AV| 偷拍精品一区二区三区| 青娱乐福利99| 强奸乱伦免费网站| 久操网视频| 性色AV网站| 日本熟妇浓毛hdsex| 久操频道免费在线呗看| 91n欧美| 国产在线激情| 翔田千里AV无码秘 三区| 大奶的诱惑| 超清中文乱码字幕| 亚洲无吗在线视频| 人人透人人操| 亚洲激情网一二三四区| 97国产精品国| 欧美中字不卡| 亚洲丝袜诱惑| 亚洲男人综合| 国产视频一区二区免费| 伊人久久婷婷| 亚洲图片欧美91N| 亚洲男人的天堂一区二区| 九九热精品免费视频| 夜夜嗨一区二区| 午夜精品99久久久久传媒| 色噜噜综合在线| 日韩AV一区二区三区三州三州| 成 人 影视 一区 二区 三区 四区| 大香蕉碰碰| 久久精品国产亚洲粉嫩| 无码78| 97超碰香蕉| 黄色片A级一区二区三区| 狠狠色噜噜狠狠狠狠2018| 九九精品99| 天天干天天操天天干天天操| 夜夜嗨一区二区| 中文字幕艹艹| 天天影视91看看| 日韩小电影| 最新日产中文在线麻豆| 一牛影视久久久一区二区三区| 久久中日麻豆| 少妇无码999| 99久久精品欧美国产| 手机在线视频国内精品| 国产精品天美传媒| 中文字幕一区二区无码成人| 国产91av在线播放| 开心五月激情网| 亚91亚洲网| 熟女露脸激情自拍视频| 日本精品一级二级三级| 欧美日韩国产色图在线| 区二区亚洲婷| 超碰97护士| 久久精品国产亚洲AV嘿嘿| 久草婷婷| 欧美日韩国产色五月综合在线 | 婷婷视频在线免费观看| 啊啊啊啊啊好大好舒服想要| 亚州性色| 免费在线观看国内色片网站网址| 强上我不卡卡| 一区二区三区国产在线播放| 麻豆这里只有精品| 久久人妻无码毛片A片麻豆| 亚洲综合在线91| 激情无码日韩| 91真人天天在线| 一区二区高清视频| 日本不卡三级网在线播放| 欧美天天影院| 超碰99在线| 香蕉大久久久| 欧美亚洲日本激情在线| 麻豆区久久久久亚| 日韩AV熟女乱伦| 久伊人网78| 欧美日韩性爱无码| 色臀aV| av天堂精品久久| 麻豆乱码久久精| 日韩熟女精一区二区三区不卡| 五月天激情四射| 狠色婷婷久久一区二区三区_| 免费日韩黄片| 夜色97| 亚洲成人日韩小说| 久草精品一区 | 日韩在线视频1234| 三及片网站| 综合久| 97精品视频在线| caoni国产亚洲av| 啊啊啊要高潮了| 天天操人人操狠狠插| 九九久久99| 成人无码在线超碰网| 爱射综合| 大地资源在线观看中文第二页| 亚洲欧美日韩不卡人妻| 精品1区2区3区| 久久超碰天天| julia国产在线| 夜夜春夜夜操| 亚洲色欧| 欧美第一页| 日韩在线一区高清在线| 久久精品电影| 啊灬啊灬啊灬好深灬快高潮了动漫-国产字幕国产在线观看-B049AV | 九九Av| 大但人体久久久久| 日韩成人在线性爱视频| 91色色综合| 美女黄频a美女大全免费皮| 男人天堂免费| 91狠| 蜜桃视频成a人v在线| 日本免费一区二区不卡| 99色视频| 天天搞在线综合网| 91国产丝袜白虎| 亚洲欧美精品一区天堂久久| 精品视频在线观看精品| 91国精产品| 国产后入精品| 亚洲精品成人激情在线| 夜夜爽夜夜操| 亚洲人精品午夜不卡| 九九天堂| 四虎影院成年人片| 一级毛片久久久久久久女人18| 91热爆在线| 97最新在线播放视频| 欧美精品99久久久| 无码在线亚洲| 欧美 日韩 国产传媒| 懂色AV一区二区三区| 精品人妻美妇91job| 人妻在线视频| 婷婷五月天影院| 九九99久久| 国产精品91一样| 久久AV无码1区2区3区| 无码视频一区二区| 开心五月婷婷激情| 日韩欧美视频青青| 蜜臀久久99精品久久久久久-DVD原版全| 猛交交| 精品欧美老熟女一二区| 中文字幕十五区| 亚洲国产日韩欧美熟妇在线| 日韩字幕一区| 久夜操| 美女大乳久久久久久久女人18| 91人妻中文| 亚州性色| 91九色丰满高潮| 久久色人体| 人人操人人uiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii | 99国内熟女露脸视频| 亚洲福利中文字幕在线| www.av家庭乱伦| 精品人妻一区二区三区四区| 久久精品久| 国产www色在线观看| 久久精品国产AV一区二区三区| 亚欧中文字幕在线视频| 久久欧美1卡2卡3| 丁香五月天堂网| 欧美 亚洲 偷拍自拍| 欧美日韩精品一区二区三区高清| 美女淫穴| 人人操人人操草草| 国产精品原创巨作?v网站| 久久精品一区二区三区蜜桃臀| 67194国产| 自怕偷自怕亚洲精品| com 首页 18岁 禁区 女优 免费 精选 同城 | 亚洲人妻熟妇三十三区| 99热在线观看| 中出欧美| 欧美 亚洲 综合 制服| 国产精品无码av嫩草| 自拍鲍鱼一区在线高清观看免费| 国产一区96在线| 蜜臀99久久精品| 欧美日韩大黄片| 九九热最新| 欧美亚洲丝袜美女电影| 宅男91视频在线播放| 婷婷五月色| 天天操天天插| 91黑丝少妇| 口爆综合网| 麻豆天美制片厂网站视频| 激情四射婷婷四五月天| 亚洲熟女综合| 99这里都是精品| 大茄子熟女AV导航| 亚洲国产另类在线中文| 把腿张开老子CAO烂你| 日韩人妻一区二区精品| 人妻天堂综合网| 日han少妇无码| 亚洲中文字幕久久无码精品| 12一15性XXXX粉嫩国产| 囯产操逼片| 五月丁香影院| 精品熟妇视频一区二区| 人人操欧美风骚| 欧美黄片免费在线观看视频| 天天影视色香色欲| 不卡一区视频| 综合伊人网12色| 国内精品久久久久影院亚洲| 天天舔九色婷婷| 阿姨一区二区免费视频-高清正片西瓜视频下载app-T450AV | 欧美综合色,www| 97精品一区二区视频| 91丨熟女丨丰满熟女| 久久国产三区| 综合熟妇一区二区三区| 免费人成在线观看网站品爱网| 无码自拍SM| 亚洲少妇视频| 日本黄大片在线观看视频| 亚洲日韩成人性爱视频| 国产二区三区粉嫩在线| 在线观看中文字幕| 囯产精品一区二区三区线|亚洲人成无码网WWW动漫|国产精品免费一级... | 91国产美女丝袜足交精品视频| 亚洲,欧美,综合网| 免费看国产曰批40分钟怎么下载| 超碰日本97美女人妻人人玩人人爱| 九九九九九九九九九九精品视频| 日韩一级欧美一级国产一级台湾| 啊好大好舒服| 亚洲在线91| 8050午夜少妇无码| 伊人伊人LD| 无码精品久久久久久亚洲| 日日夜夜狠狠| 91观看 国产白丝| www欧美性爱| 精吧天堂| 亚洲暴力强奸AV| 欧美亚洲厕所精品偷拍91| 性夜影院爽黄A爽免费动漫| 丁香六月啪啪| 97久久国产精品女不卡| 久久99热这里只频精品6学生| 中文一区二区| 破苞ⅩXXX性无码动漫无码| 亚洲天天精品| 久久性爱城| 国产美女91| www九九热| 国产精品夜夜夜| 久操不卡视频| 综合五月天| 91色情黑丝搞鸡在线观看一区二区三区三州| 久久久久久久久久久久久女过产乱-少妇高潮一区二区三区喷水-成人AV | 日本国产亚洲一区在线观看| 中文字幕乱碼在线| 午夜啪啪片| 成人欧美日超碰| av凤凰久久久| 丁香九月婷婷| 超碰97男人| 中文字幕一区二区韩| 香蕉色网| 人妻熟女午夜精品在线| 亚洲色综合| 亚洲自拍一区夜夜操| 熟女精品va中文字幕| 日日干夜夜骑| 超碰资源亚洲97| 男女啪啪啪18禁网站| a人欧美综合天堂麻豆| 美国人人操人人操| 91精品国产一区三一| 高潮内射在线| 乱伦熟女区| 色图综合网| 亚洲91网站| 国产精品视频精品一二| 天天综合网网欲色| 色网综合网| 99免费在线视频| 欧美18 在线观看| 91处女在线视频| 日本熟妇一区二区三区| 污污汅18禁网站在线永久免费观看 | 欧美 亚洲| 超碰中文字幕人妻草一区| 国产综合网站在线播放| 永久电影三级在线观看| 97超级色碰碰| 亚洲男人的天堂V| A片 AV一级在线播放观看免费| 美女诱惑一区| 大鸡巴久久| 久久大陆| 最新av在线| 六六久久日韩不卡| 中文字幕日本久久| av最新免费中文字幕| 久久9精品| 69丨亚洲丨精品丨入口免费播放| 啊啊在线| 69人妻精品丰满熟女区| 少妇二级| 韩国一级婬片A片AAAAA| 国产宅男宅女在线观看| 偷拍精品一区二区三区| 91热| 91视频女生| 情侣操 逼视频99| 超碰爽人妻熟女Av| 97午夜剧场日韩| 亚卅熟女乱色| 精品国产乱码久久久久久口爆网站| 欧美一区二区男人天堂| 91香蕉国产尤物视频| 麻豆天美在线| 中文字幕青青草| 女上位精品在线| 亚洲熟久久| 免费网站观看www在线观| 久都青青视频| 99re这里只有精品中心播放| Julia在线播放亚洲久久| 狠狠操综合| 欧美日韩性爱视屏免费看了| 美国aaaaa一级黄片| 精品少妇人妻av久久免费| 日韩性爱啪啪视频| 国产黄色剧情影片麻豆免费播放| 亚洲超碰97| 97香蕉网| 久热影视| 91在线视频观看国产| 欧美日产国产在线成人第一区| 天天干人人看综合| 亚洲AV成人无码一二三久久| 国产精品毛片?v一区二区三区| www.av家庭乱伦| 秋霞Av理论一级在线| 沈阳熟女高潮对白视频| 看大黄色大片原件| 一区二区三区 日韩欧美| 日本www操操操| 久久一级无码精品毛片6| 久久久久久久国产a∨| 人妻日日干| 无遮挡猛进视频免费无限观看| 免费毛片在线播放| 欧美精品人妻视频| 欧美A√综合网 | 国产精品丝袜在线| 91成人18| 国产女同视频在线播放| 黑丝自慰喷水网站| 九九AV| 亚洲熟女乱色| 午夜无码熟妇丰满人妻| 四虎影视欧美| 男女激烈网站最新| www.色操逼| 婷婷日韩一区二区三区中文字幕在线| 久久神马影院| 超碰97人妻自拍| 久久久久九九九| 丰满人妻一区二区三区四区| 久久人人妻| 中文字幕、久久精品国产2020、久久综合久久自在自线精品自、亚洲 | 亚洲国产成人精品久久久国产成人一区二区| 桃花色综合影院| 亚洲av影音先锋| 97色婷婷| 亚洲天天精品| 亚洲天堂在线怕怕视频 | 四虎影视国产精品| 在线观看一级α片刺激高潮视频| 日韩一区二区高清在线观看的| 激情五月婷婷| 男人的天堂日本东京热| 探花精品 一区二区| 国产精品呦一区二区三区| 91无码中出人妻视频| 色www精品视频在线观看| 亚洲天堂男| 国产成年精品高清在线观看91| 婷婷伊人| 亚洲少妇激情一区二区三区| 色色色日本| 超碰人人色| 人妻在线大香蕉| 日噜夜夜夜夜夜夜夜夜夜夜爽爽爽爽爽爽爽爽爽爽爽爽 | 99久久久无码国产精品性男| 东北女人av| 夜夜国自区| 老司机深夜18禁污污网站| 色香色欲天天综合网天天来吧 | 国产一区二区三区免费视频在性观看| av天堂影视中文在字幕在线中文 | 久久久精品91八戒| 色五月婷婷五月天| 黄站在线免费观看| 精品久久人妻成人网| 淫骚熟女一区二区三区| 国产高清午夜成人在线观看| 婷婷五月影院| 色噜噜人妻av中文字幕| 日操粉逼逼| 性性欧美| 成人性爱美曰韩| 91精品国久久久久久无码| 中文操逼字幕| 伊人97色天使| 国产色图乱伦| 久久免费老司机精品| 性91| 日本三级久| 欧美碰碰综合色| 巨爆乳肉感一区二区三区竹菊影视 | 99在线啪| 久久香蕉综合一本到3atv| 九九九九免费高| 成 人片 黄色大片| 亚洲色图国产另类| 日本操大逼| 久久超碰av在线| 亚洲五码一区二区三区| 99999亚洲| 免费网色网站| 日韩精品在线观看观看| 久久超碰98| 97精品熟女少妇一区| 久热久| 91高清无码下载| 韩日自拍| 激情五月激情综合网| 黄色工厂这里只有精品| 天天爽爽爽爽| 黄色片一区二区三区四区五区| 超碰97最新人妻| 国产精品嫩草影院免费| 日韩欧美麻豆| 国产精品青青草| 亚洲国产精品成人综合| 69丨亚洲丨精品丨入口免费播放| 一区二区三区机械有限公司| 葡萄牙性视频一二区| 婷婷国产精品九区| 日操粉逼逼| 亚欧美综合网| 中文字幕精品乱码| 五月大香蕉| 色综合一本| 色综合20p| 国产 码在线成人网站| 精品国产Av无码久久久伦古装| 欧美在线伊人色| 国产精品制服丝袜清纯唯美| 91A欧美电影网站| 欧美日韩国产电影| 九九综合久久| 免费一级黄色录像影片| 九九九九九精品视频| 殴美日韩m| 免费一级视频特黄色大片| 懂色av一区二区三区天美传媒| 成人久久无码www| 精品久久人妻成人网| 伊人一级免费黄片| 成人三级片一区二区三区视频| 一区二区三区四区五区高清无码永久视频 | 亚州色图欧美| 玖玖综合.com| 新婚人妻扶着粗大强行坐下| 美女91| 色色毛片| 日韩无码服务区| 国产五码丝袜屁眼| 天天色悠悠激情| 日亚韩精品视频二区三| 中文字幕久热视频在线| 91人妻少妇| 欧美韩日精品99综合| 久久m| 97色冈| 色五月av| 亚洲AV无码成人精品久久| 亚洲 无码 偷拍| 久热热| 91中出在线| 久久精品人妻一区二区| 天天看人人操屄犊摸阴| 人妻一区二区三区| 女同亚洲欧美一二三区久久电影| 色情五月丁香| 国产精品老师| 日本三级韩三级99久久| 国产一区二区视频在线播放| 国产高清在线观看欧美| 中文字幕久热视频在线| 久久受www免费人成| 东北少妇高潮zzzz| 亚洲无码电影久久久| 91殴美| 91天天综合日韩欧美| 日韩精品午夜操呦呦不卡影院| 欧美日日人人天天| 97久久国产精品| 美女骚尻视频| 淫纸中9区| 99热婷婷一区二区三| 亚洲狠狠入| 9久久久久久| 亚洲性高潮| 97天天操| 日本一区二区亚洲综合| 欧美性爱日韩高清| 在线看的av| av网页一区二区三区| 日本丝袜人妻内射| 丰满人妻无码一区二区三区| 国产AV激情无码久久无码 | 第二页中文字幕| 综合激情97| 少妇69中文| 久久99草| 清纯唯美综合| 污色区网站| 国产最火爆久久国产网站网站| www.99色| 一级性爱aaaa| 午夜激情床戏激情| 欧美情色贴图| 伊人宅男大香蕉| 亚洲精品97久久| 性久久久| 亚洲AV成人无码一区二区三区在线观看| 久久欧美性爱视频| 国产高清1234区| 色香在线| 久久在肏| 亚洲免费在线探花| 五月激情在线| 蜜桃精品视频一区| 欧美亚洲特P| 日韩性爱小视频| 亚洲五码一区二区三区| 日韩乱码Av| 欲射影视| 91欧美网| 国内毛片婷婷六月色| 久草婷婷| 91成人18| 美女操逼福利视频| 久久麻豆一区二区| 国产久久日| 东北女人无套内谢视频| 日本视频在线观看污污污| 草草影院在线视频| 东方亚洲在线操逼天堂| 高清国产精品福利网站| 一起草精品人妻| 熟妇人妻一区二区| 97Ai亚洲| 国产女乱淫真高清免费视频| 欧美亚洲日韩人妻在线观看| 欧美黑人91| 亚洲āv网址在线观看| 婷婷激情综合网| 另类图片亚洲加勒比另类图片亚洲加勒比另类图片亚洲加勒比 | 狠狠入| 国产精品爽爽v| 色爱综合网| 超碰9 7女人| 少妇一区二区三区高速| 综合久草| 亚洲男人的天堂va亚洲男人社| 99精品视频在线观看免费| 91暧暧| 97超碰中文在线| 中文字幕在线高清男人的天堂 | 国产高清视频无码在线| 夜夜操2028| 我要色综合网站| 欧美强奸乱能| 久久久九九九九| 无码外流操逼视频| 久久国产视频专区一二三| 欧美性爱一区二区三区| 操屄不卡视频| 人乳av| 麻花豆传媒剧国产MV出差| 日韩专区数据列表-第3230页-精品国产一区二区三区香蕉 久久99熟女人妻中文字 | 日逼国产| 国产免费一区| 特级毛片特黄久久免费看| 亚洲永久AV无码精品秋霞| A级在线视频| 青青11操操操操操操操操| 2020中文字幕在线观看| 九九热精品| 成人性交免费视屏| 99少妇精品视频| 中文字幕在线免费观看 | 日韩综合97P| 丰满人妻无码一区二区三区| 麻豆伊人网| 色狠狠 - 百度| 国产精品国产| 亚洲操人| 国产久久久| 情色日播放AV| 无码 黑人一区二区三区| 99xav| 日韩精品 视频一区二区| 大香蕉92| 欧美成人都市人妻| 私人尤物在线精品不卡| 欧美日韩少妇色情| 青娱乐国产精品| 亚洲色棕合| 99色综合| 性爱综合一区二区| 亚洲素人网| 综合激情婷婷| 凹凸视频在线一区二区| 欧美日韩亚洲五月天婷婷| 色色色天美视频| 上床啊啊啊| 人人综合| 粉嫩绯色AV一区二区在线| 少妇无码av专区线| 日韩欧美三级| 丝袜综合| www.yw尤物| 26uuu久久| 麻豆区久久久久亚| 麻豆 欧美 日韩| 蜜乳AV一区| 欧美性色网| www.高清无码诱惑一区.com| 久久婷色| 亚洲精品国产专区在线观看| 97鸡把在线视频| 久久只有精品一区二区三区| 欧美综合区| 无码高清少妇久久| 亚洲精品熟妇1区2区3区。| 一区麻豆 高清中文字幕| 欧美黑人精品一区二区| 午夜性生活av免费在线看| 超碰在97| 日本熟人妻中文字幕在线|...久久国产精品-国产精品_日本一区二区三区中文字幕 | 观看视频图片一区二区三区| 欧美一区二区观看在线| 国产真实子伦对白| 九九久精品| 日韩精品99久久久久久中文字幕| 开心激情婷婷| 国产精品成人福利在线| 久久亚洲AV无码白度| AV在线播放网址| 久久只有精品一区二区三区| 91婷婷| 在线看片国产精品每日更新| 色吧 综合| 国产sv美女内射| 人澡逼| 日韩9999| 夜夜操夜夜爽夜夜高潮| 色婷五月天| 亚洲欧美精品福利在线| 国产Aα| 強姦亂倫a| 天天草天天日| 欧美超碰在线| 青青草一区二区高清无码视频| 好吊爽好吊爽在线视频,中文字幕精品一区二区日本,国产良妇出轨视频在线观看, | 少妇大屁屁| 午夜精品久久久99热蜜桃的功能特点| oumeisetupian| 久久久久精| 精品精品精品| 成人资源中文字幕在线观看天天| 国产精品视频白浆免费| 中文字幕精品一区二区精| 久久透逼视频| jazzjazz国产精品麻豆| 97亚洲综合影院| 国产乱子伦久久精品综合一区二区三| 亚洲男人天堂网站| 色区97| 2020中文字幕在线观看| 精品人妻一区二区三区四区| 欧美色97| 亚洲动态色图| 精品99999| 综合久久久久久久久91| a片 xxxx受爽视频| 98人妻精品一区二区色欲| 99久久无码| 高清国产精品无码| 这里只有精品视频在线观看麻豆| 亚洲国产av中文字幕久久| 欧美性生活免费网| 国产精品久久久久亚洲av| 一本一道波多野毛片中文在线| 国产精品一区午夜福利| 久久久久国产精品片区无码直播| 一区二区三区欧美激情| 九九九九九九免费视频| 午夜精品久久久99热蜜桃的功能特点| 欧美色图在线视频少妇| 亚洲春色欧美| 久久久人妻| 岛国在线国产| wwwcaobibi| 91超级碰碰碰| 久久天天摸| 中文字幕女同在线| 夜夜高潮夜夜爽国产伦精品| 97精| 欧美黄色片在线播放| 在线无码操| 男人天堂2012| 男人 天堂 日 亚洲| 91热色| 亚洲人天堂| 艹精品| 99在线免费视频| 欧美五区| 中日韩久久久免费看| 欧美人妻少妇| 免费在线黄片视频| 国产剧情一区在线观看| 亚洲少妇激情视频| 久草免费在线视频| 俄罗斯一区二区视频在线观看| 韩国一级做A片免费的| 日韩AV电影网站| 久久99草| 国产偷人伦激情在线观看| 亚洲精品影视老司机| 欧美亚洲玖玖玖| 加勒比人妻综合| 亚洲欧美成人网站AAA| 精品久久久久久中文| 亚洲男人天堂2019| 四虎免费视频| 亚洲影院365| 久久大香蕉| 97bbn| 91久久久亚洲| 伊人久久婷婷| 色哟哟av网址| 69av一区二区三区| 六月婷婷综合| 色九九九九九九| 影音先锋每日最新资源在线观看| 色99视频| 九九热午夜欧亚国产视频| 日本乱人伦片中文三区| 亚洲中文字幕网| 国产精品乱码久久久久久| 中文字幕精品一区二| 艹我哪美一区无码| 蜜桃传媒视频第一区入口在线看| 亚洲欧洲无码bt精品合集| 99热综合| 91白虎| 日本午夜福利影院| 日本三级韩国三级美三级91| 韩国免费播放一级毛片| 资源在线观一 二| 91精品导航| 国产农村一一级特黄毛片| 久啪| 强奸乱伦大香蕉| 欧美视频第二页| 午夜国产综合视频在线观看| 蜜色网色哟哟| 中文字幕乱亚洲美女精品一区| 天天干天天狼在线视频| 97操综合| 97最新在线播放视频| 色香综合天天影视综合| 亚洲AV无线| 天美传媒av在线| 玖玖爱免费观看视频| 欧美高潮| 操逼日韩无码| 综合色区偷拍| Julia在线播放亚洲久久| 亚洲黄色电影| 91美女中出| 亚州色综合| 91青视频| 欧美A片中文字幕| 国产女同性恋视频| 亚洲天堂中文字| www被窝色com| 国模精品娜娜一二三区 | www.yw尤物| 少妇久久久久久久| 久久99手机免费视频| 久久久久久亚洲Av无码| 91路www| 91人人臊| 久久久亚洲| 欧美熟女妇同| 国产精品视频白浆免费| 深夜激情| 中文字幕一区二区三区人妻少妇在线| 国产毛片片精品天天看视频| 佐山爱中文字幕| 美国aaaaa一级黄片| 精品国产乱码久久久| 久久大香蕉手机高清| 免费黄色片。| 91大香蕉伊人| 国产专区路线| 日本一区二区不卡精品| 伊人九九| 97视频620| 久操大香蕉| 26uuu国产亚洲综合| 色爽——AV| 麻豆2区1区天美| 91碰超| 欧美美女视频| 国产天美传媒精品| 婷婷激情五月综合| 天天狠操| 2017天天操| 色香伊人| 97视频观看| 男人的天堂一区三区| 国产精品点击进入在线影院高清 | 大伊香蕉在线视频免费| 欧美性第一页| 久久久精品视频欧州站| 啊啊啊啊啊操我视频| 久久久久久AV无码免费网站| 欧洲性爱无码区| 色欧美色交综合| 91网18| 激情五月天网站| 青娱乐国产盛宴视频| 麻豆天美一区二区| 加勒比无码毛片| 97 国产一区| 久久国产三区| 久久香蕉综合一本到3atv| 天堂v无码免费视频| 99热线麻豆 | 盗摄女人妻在线| 亚洲色图欧美一区二区不卡| q2午夜理论片夜色av| 国产精品2020| 校园春色制服丝袜中文字亚洲| 亚洲精品影视老司机| 五月天婷婷在线看| 久久久久久加勒比| 亚洲成人在线资源| 色网1| 日韩欧美丝袜诱惑| 中文字日本乱码| 爽爽淫人网| 无码国产精品午夜不卡(| 日韩免费大片一级播放| 亚欧毛片基地国产毛片基地| 97免费在线观看| 亚洲美女精品九九视频| 综合熟妇一区二区三区| 麻豆黄站| 久久妇| 强奸熟女一区二区三区 | 国产女人与拘做受视频免费| A级片日韩欧美国产欧美视频精选观看| 欧洲综合色| 精品国产乱码久久久A| 色九九九九九九| 9 1超碰九色| 91 国产丝袜在线播放-百度| 亚洲精品不卡一二三区| 狠狠躁日日躁夜夜躁A| 欧美亚洲涩涩| 欧美色图 人妻| 中文一区在线日| 综合av影片| 91精品久久久久久久久久| 日本一久是| 亚洲涩图欧美| 国产熟码AV| 欧洲亚洲人妻无码久久三区四区| 综合熟妇一区二区三区| 久久久久久久久久久精| 男人的天堂VA| 天天综合-91入口| aa片毛片| 久热在线精品免费观看| 国产精品嫩草久久久久| 午夜120视频在线观看| 草莓精品视频| 操人91| 欧美色偷拍| 亚91亚洲网| 天天躁狠狠躁av| 亚洲加勒比色图| 蜜臀99久| 婷婷操视频| 一牛影视成人片免费| 国产吞精a级片激情电影| 六月丁香婷| 116美女午夜| 伊人991| 33044男人的天堂深夜备| 女优大全 - 91n| 激情小说日韩无码| 欧美大香蕉专区网| 激情五月综合网| 国产91精品久久久久久久网曝门| 亚洲自拍欧美色综合| 国产怡红院在线| 午夜啪| 欧美熟女操屄| 99精品丰满人妻无| 日韩精品人妻中文字有码在线| 97在线观看免费| 人妻夜夜爽天天爽三区麻豆AV网站| 成人AV超碰免费在线| 日韩精品永久在线观看| 日韩在线视频1234| 亚洲drav色图| 97爱| 免费A V在线播放| 91在线|亚| 在线五区| 毛片久久| www.超碰在线| 人妻人人澡人人爽人人| 欧美色老汉| 熟妇的味道HD中文字幕| 丁香激情五月天| 国产亚洲日本| AAAA级日本片免费视频| 久久婷婷综合国际产色怕| 性色高清在线| 久草这里只有精品 | 蜜臀国产AV中文字幕| 亚洲性猛交| 伊人天天久久动态图| 嫩草影院在线观看精品 | 天天谢天天干| 日韩精品一区二区三区四虎影视| 97精品国产精品免费观看| 97久久超碰| 91chinese在线| 亚洲欧美精品久| 国产一级内射高清视频| 久久久97| 日韩丨制服丨中文|在线| 永久电影三级在线观看| 狠狠干综合| 亚洲se电影| 欧美大香蕉同搞| 欧美综合色站| 久久男人天堂| 亚州精人品大香蕉| 久久亚洲欧美一区二区三区-亚洲国产精品第一区二区 | 国内毛片欧美香蕉精品| 五月天婷婷小说| 国产AV天美传媒一区二区三区 | 任你干在线视频| 国产Av超碰| 和协无码影院| 欧美亚洲自拍另类人妻| 日韩免费人妻色情网站| 精品国产乱子伦一区二区三区,精品一| 无色无码| 日韩八十路老熟女| 岛国大片在线观看网站入口| 九九成人精品| 日韩簧片免费看| 精品人妻一区二区免费蜜桃| 四虎精品永久在线播放| 四虎 精品 WWW| 久久大黄片| www.97在线| 五月亭亭六月丁香| 日本三级人妻a人妻一在线| 九九AV| 久久精品亚洲婷婷| 亚洲国产精品成人久久蜜臀| 国产伊人自拍| 97超碰磁| 久久曰曰| 99热 按摩 日韩| 久久精品三级影视| 无码 黑人一区二区三区| 精品福利| 亚洲色图欧美色图另类图片| 亚洲另类春色| 亚洲影院成人| 600国产精品视频| 日日骚av| 欧美91网| 性感美女91影视| 九九久精品| 久操视频免费观看| 色哟哟AV| 青青草久草| 亚洲精品性爱片| 蜜乳AV一区| 涩五月婷婷| 亚洲欧美性生活| 亚洲日韩少妇一道本视频| 99久久久| 麻豆国产视频精品观看| 黄片无码在线制服| 天天狠| 北京美女一区二区| 日夜尻逼网| 少妇久久久久久久| 国产精品久久久久久久毛片1| 久久男女激情视频网站| 欧美图片偷拍| 日本黄色天堂| 极品白嫩美少妇在地板上位骑射淫水泛滥| 亚洲精品97p| 中国韩国明星一极片一区乱码毛片人妻熟女一区二区三区 | 欧美亚洲激情小说| 香一区二区三区| 成人黄页| www.男人的天堂| 激情五月综合开心五月| a级成人毛片免费视频高清| 99精品在线| 啊啊啊啊在线观看网址| 伊人久久大香线蕉亚洲五月天,青草青草欧美日本一区二区,欧美日产欧美日产国产 | www.91逼逼.com| 欧美黄色片AAAAA| 欧美精品丝袜久久久中文字幕| 四虎视频在线观看| 欧美小说区视频区| 欧美综合娱乐久久| 六月婷婷激情| 丝袜翘臀后入欧美校园亚洲自拍另类小说一区中文字幕少妇诱惑 | 麻豆福利视频导航| 加勒比综合在线| 无码日韩人妻av一| 国产黄a三级三级三级av在线看| ai欧美亚洲小说| 婷婷五月天激情四射| 久久性爱免费送| 亚洲免费97免费| 成人精品在线免费视频| 亚洲欧洲综合视频在线| 97硬碰| 加勒比综合网| 大香蕉综合网| 欧美,日韩,中文,另类| 日韩欧美俄罗斯A片| av午夜玫瑰| 午夜成人爽爽爽爽A片李冰冰| 偷窥自拍亚洲天堂网爆| 午夜精品久久久久久久99| 少妇啪啪自拍| 久久精品中文| 亚洲蜜乳av| 囯产精品强| 午夜黄色免费在线观看| 动漫av中文| 操碰97| 天天cao在线| 久久精品一区二区三区不卡| 国内一级精品| 99热97| 1人人看人人摸人人操| 亚洲成人妻日韩在线| 亚洲精品啪视频| 一二区在线观看视频| 熟女人妻av在线资源,黄色的资源| 人人妻人人玩人人澡人人爽| 97一区二区蜜臀| 亚洲精品日韩国产欧美| 欧美性第一页| 欧美一区二区三区黄色影视| 91国产丝袜美女| 男人的天堂色偷偷青青草视频婷婷网| 国产精品盗摄 偷窥盗摄| 熟女熟妇伦久久影院毛片一区二区| 噜噜噜无码AV一级一级久久影院| 99中文字幕| 国产精品动态一区二区三区四四| 丁香五月激情网| 久久久久久久伊人精品| 欧美美女视频| 日本熟妇自慰性高潮一区二区三区| 国产欧美日韩在线观看麻豆传媒公司| 少妇一区二区三区高速| 久久久久久999| 亚欧美色图| 人妻少妇精品久久久| 国产精品久久久久久夜夜夜| 欧美人人AAA| 操逼视频亚洲| 伊人精品久久网站| 亚洲一区操| 国产精品点击进入在线影院高清| 蜜臀久久99精品久久久久电影| 是还免费视频1727我| 久草色悠悠在线视频|