国产成人欧美一区二区三区vr_久久国产精品人人爽人人爽_国产精品永久免费播放_肉欲啪啪a∨无码精品一区二区_国产超短裙jk丝袜在线_亚洲AV片高清资源在线观看_国模无码一区二区三区久久_国产成年人未进视频_中文字幕无码精品夜_一区二区三区在线视频免费看_亚洲成AV人片在线观看网址_日本激情视频高清综合久久_亚洲午夜视频福利_国内大量揄拍人妻精品視_久久国产精品福利二区三区

ARTICLE DETAIL

資訊詳情

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

Rust所有權(quán)與借用檢查:編譯期內(nèi)存管理實(shí)踐

Rust所有權(quán)與借用檢查:編譯期內(nèi)存管理實(shí)踐 寫 Rust 這幾年被問(wèn)得最多的一句話就是“所有權(quán)到底是個(gè)啥”。我一直覺(jué)得這個(gè)中文譯名有點(diǎn)誤導(dǎo)聽(tīng)起來(lái)像某種法律概念實(shí)際上它描述的是一件特別樸素的事一塊內(nèi)存由誰(shuí)負(fù)責(zé)釋放、什么時(shí)候釋放、釋放之前誰(shuí)有資格讀寫。C 里這件事靠人腦記賬Java、Go 里這件事交給運(yùn)行時(shí)在后臺(tái)掃Rust 選了第三條路——把賬本寫進(jìn)類型系統(tǒng)讓編譯器在編譯期替你記。代價(jià)是你得學(xué)會(huì)跟編譯器講道理收益是運(yùn)行時(shí)沒(méi)有停頓、沒(méi)有懸垂指針、沒(méi)有雙重釋放單線程代碼里的迭代器失效問(wèn)題基本絕跡。這篇筆記把所有權(quán)、借用檢查、生命周期標(biāo)注、智能指針這幾塊串起來(lái)講重點(diǎn)放在“它怎么影響內(nèi)存管理”這個(gè)角度而不是復(fù)述語(yǔ)法手冊(cè)。適合已經(jīng)能寫點(diǎn) Rust 但總被借用檢查器攔下來(lái)的人也適合從 C 或 Go 轉(zhuǎn)過(guò)來(lái)、想搞清楚心智模型差異的人。下面所有報(bào)錯(cuò)和改法都是我實(shí)際踩過(guò)的代碼可以直接抄去跑。1. 三種內(nèi)存管理路線Rust 為什么挑了最難的這條1.1 手動(dòng)管理與垃圾回收各自的賬單先把三條路擺在桌面上對(duì)比不然后面很多設(shè)計(jì)取舍會(huì)顯得莫名其妙。手動(dòng)管理C、C 的裸指針路線把釋放時(shí)機(jī)完全交給開(kāi)發(fā)者性能上限最高內(nèi)存布局最可控代價(jià)是任何一次疏忽都會(huì)變成線上事故而且這類事故往往在壓力大的時(shí)候才暴露。垃圾回收J(rèn)ava、Go、C# 的默認(rèn)路線把釋放交給運(yùn)行時(shí)開(kāi)發(fā)者寫得舒服代價(jià)是內(nèi)存占用曲線偏高延遲不可預(yù)測(cè)遇到大堆的時(shí)候一次回收能帶來(lái)幾十毫秒的抖動(dòng)。Rust 的所有權(quán)系統(tǒng)是第三條路編譯器在編譯期為每個(gè)值推導(dǎo)出唯一的負(fù)責(zé)方負(fù)責(zé)方離開(kāi)作用域就自動(dòng)釋放檢查全部發(fā)生在編譯期運(yùn)行時(shí)不需要任何額外指令。路線釋放時(shí)機(jī)運(yùn)行時(shí)開(kāi)銷典型風(fēng)險(xiǎn)延遲可預(yù)測(cè)性手動(dòng)管理開(kāi)發(fā)者調(diào)用 free/delete接近零懸垂指針、雙重釋放、泄漏高垃圾回收運(yùn)行時(shí)掃描判定5% 到 30% 不等看堆大小停頓抖動(dòng)、內(nèi)存峰值高低所有權(quán)系統(tǒng)作用域結(jié)束自動(dòng) drop編譯期檢查運(yùn)行時(shí)為零學(xué)習(xí)曲線、改寫數(shù)據(jù)結(jié)構(gòu)高這張表里最關(guān)鍵的一列是“運(yùn)行時(shí)開(kāi)銷”。Rust 的所有權(quán)檢查在編譯完成后就消失了生成的機(jī)器碼里沒(méi)有任何一條指令是用來(lái)“檢查所有權(quán)”的這叫零成本抽象。你付出的是編譯期的思考成本和偶爾的改寫成本換來(lái)的是運(yùn)行時(shí)的確定性。1.2 所有權(quán)本質(zhì)上是一套編譯期推導(dǎo)出來(lái)的引用計(jì)數(shù)我習(xí)慣用引用計(jì)數(shù)來(lái)類比所有權(quán)這個(gè)類比能解釋掉八成的疑惑。真正的引用計(jì)數(shù)比如RcT是在運(yùn)行時(shí)維護(hù)一個(gè)整數(shù)每次克隆加一每次銷毀減一減到零就釋放。所有權(quán)系統(tǒng)做的事情幾乎一樣區(qū)別在于編譯器在編譯期就能推導(dǎo)出每個(gè)值的引用計(jì)數(shù)永遠(yuǎn)是 0 或 1既然結(jié)果只有兩種那就不需要在運(yùn)行時(shí)存這個(gè)整數(shù)了直接把它編碼進(jìn)類型檢查規(guī)則里。所以String被賦值給另一個(gè)變量之后原變量立刻失效——因?yàn)樵诰幾g器的賬本上這個(gè)值的所有者已經(jīng)換人了舊主人再訪問(wèn)就是越權(quán)。這個(gè)類比還能解釋另一個(gè)現(xiàn)象為什么RcT在 Rust 里被歸到“智能指針”而不是“所有權(quán)”里。因?yàn)橐坏┠阏娴男枰鄠€(gè)所有者編譯期就沒(méi)法推導(dǎo)出唯一負(fù)責(zé)方了只能退回到運(yùn)行時(shí)記賬這就是Rc和Arc存在的原因。理解了這個(gè)層次關(guān)系你就不會(huì)覺(jué)得RcRefCellT是一堆奇怪符號(hào)的堆砌而會(huì)明白它是“編譯期賬本不夠用時(shí)的降級(jí)方案”。1.3 編譯期到底擋住了哪幾類事故具體一點(diǎn)所有權(quán)加借用檢查主要攔四類問(wèn)題。第一類是釋放后使用C 里指針指著的內(nèi)存已經(jīng)被free掉讀出來(lái)是臟數(shù)據(jù)Rust 里編譯器直接告訴你這個(gè)值已經(jīng) move 走了。第二類是雙重釋放兩個(gè)指針指向同一塊堆內(nèi)存析構(gòu)函數(shù)跑兩遍堆管理器直接崩Rust 里因?yàn)橹挥幸粋€(gè)所有者drop只會(huì)執(zhí)行一次。第三類是迭代器失效這是 C 里最陰的一類 bug往vector里push_back之后原來(lái)的迭代器可能指向已釋放的舊緩沖區(qū)Rust 里你在遍歷v的同時(shí)調(diào)v.push()會(huì)直接編譯失敗。第四類是數(shù)據(jù)競(jìng)爭(zhēng)多個(gè)線程同時(shí)讀寫同一塊內(nèi)存且沒(méi)有同步Rust 靠Send和Sync兩個(gè)標(biāo)記 trait 在編譯期就把不安全的共享?yè)醯?。我印象最深的是第三類。早年?C 的時(shí)候在一個(gè)循環(huán)里刪元素導(dǎo)致迭代器失效程序在小數(shù)據(jù)量下跑得好好的上線之后數(shù)據(jù)量上來(lái)才開(kāi)始隨機(jī)崩潰查了兩天才定位到。換成 Rust 之后這種寫法連編譯都過(guò)不去等于把調(diào)試成本從線上挪到了敲代碼的那幾分鐘。2. 三條鐵律落地move、Copy、Clone 在內(nèi)存里到底做了什么2.1 三條規(guī)則逐條對(duì)照內(nèi)存行為所有權(quán)的規(guī)則只有三條但每一條都對(duì)應(yīng)著實(shí)實(shí)在在的內(nèi)存動(dòng)作。第一條每個(gè)值有且只有一個(gè)所有者。第二條同一時(shí)刻只能有一個(gè)所有者。第三條所有者離開(kāi)作用域值被丟棄。這三條合起來(lái)的效果是任何一塊堆內(nèi)存的釋放點(diǎn)都是唯一且確定的編譯器在生成代碼的時(shí)候就知道該在哪里插入釋放調(diào)用不需要運(yùn)行時(shí)判斷。拿String舉例。let s1 String::from(hello);這一行會(huì)在棧上放一個(gè)三元組指針、容量、長(zhǎng)度在堆上放五個(gè)字節(jié)的數(shù)據(jù)。接著let s2 s1;這一行做的事情是把棧上那 24 個(gè)字節(jié)復(fù)制一份給s2堆上的數(shù)據(jù)一個(gè)字節(jié)都不動(dòng)然后編譯器在符號(hào)表里把s1標(biāo)記為失效。如果你這時(shí)候?qū)憄rintln!({}, s1)編譯器報(bào) E0382意思是使用了已經(jīng) move 走的值。注意這里沒(méi)有發(fā)生任何堆內(nèi)存分配或復(fù)制move 對(duì)String這類類型來(lái)說(shuō)是常數(shù)時(shí)間操作。2.2 move 不是“搬家”是所有權(quán)憑證的轉(zhuǎn)移很多人以為 move 會(huì)把堆上的數(shù)據(jù)搬到新地址這是個(gè)誤解。move 搬的只是棧上那個(gè)描述符堆數(shù)據(jù)原地不動(dòng)。這也解釋了為什么對(duì)大對(duì)象做 move 是廉價(jià)的VecT裝一百萬(wàn)個(gè)元素move 一次也只復(fù)制 24 個(gè)字節(jié)的頭部。真正昂貴的是clone那才是老老實(shí)實(shí)把堆數(shù)據(jù)復(fù)制一份。我用一段代碼把這個(gè)差別量化一下你可以直接跑fn main() { let v1: Vecu64 (0..1_000_000).collect(); let start std::time::Instant::now(); let v2 v1; // move只復(fù)制頭部 println!(move 耗時(shí): {:?}, start.elapsed()); let start std::time::Instant::now(); let v3 v2.clone(); // clone復(fù)制全部堆數(shù)據(jù) println!(clone 耗時(shí): {:?}, start.elapsed()); println!({} {}, v3.len(), std::mem::size_of::Vecu64()); }實(shí)測(cè)下來(lái) move 通常是納秒級(jí)clone 一百萬(wàn)個(gè)u64大概在幾百微秒到一毫秒之間取決于內(nèi)存帶寬。這個(gè)差距在高頻路徑上是致命的所以我養(yǎng)成一個(gè)習(xí)慣函數(shù)簽名里能傳引用就傳引用確實(shí)需要轉(zhuǎn)移所有權(quán)才用 move絕不為了圖省事到處寫.clone()。2.3 Copy 與 Clone 的邊界怎么劃Copy和Clone經(jīng)常被混為一談其實(shí)差別很大。Copy是一個(gè)標(biāo)記 trait表示這個(gè)類型的值可以按位復(fù)制賦值之后原變量依然可用。能實(shí)現(xiàn)Copy的類型有兩個(gè)硬性條件所有字段都是Copy并且這個(gè)類型本身沒(méi)有實(shí)現(xiàn)Drop。整數(shù)、浮點(diǎn)數(shù)、布爾、字符、裸指針、以及由它們組成的固定大小數(shù)組和元組都是Copy的。String、VecT、BoxT都不是因?yàn)樗鼈児芾碇褍?nèi)存按位復(fù)制會(huì)導(dǎo)致兩個(gè)所有者指向同一塊堆這正是所有權(quán)系統(tǒng)要避免的。Clone則是一個(gè)普通 trait需要你顯式調(diào)用.clone()它允許你自定義復(fù)制邏輯比如深拷貝堆數(shù)據(jù)。任何類型都可以實(shí)現(xiàn)Clone包括實(shí)現(xiàn)了Drop的類型。這里有個(gè)常見(jiàn)的性能坑給一個(gè)大結(jié)構(gòu)體derive(Clone)之后在循環(huán)里順手寫.clone()傳參編譯器不會(huì)提醒你代碼跑起來(lái)才發(fā)現(xiàn)慢得離譜。我的做法是只有在確實(shí)需要獨(dú)立副本的地方才 deriveClone而且在大結(jié)構(gòu)體上會(huì)刻意不 derive逼著自己去想清楚到底該傳引用還是轉(zhuǎn)移所有權(quán)。順便說(shuō)一個(gè)實(shí)測(cè)有用的小技巧用std::mem::size_of快速看一眼類型的棧上開(kāi)銷很多“為什么這個(gè)結(jié)構(gòu)體這么大”的疑惑一測(cè)就清楚了fn main() { println!(String {}, std::mem::size_of::String()); // 24 println!(str {}, std::mem::size_of::str()); // 16 println!(Boxu64 {}, std::mem::size_of::Boxu64()); // 8 println!(OptionBoxu64 {}, std::mem::size_of::OptionBoxu64()); // 8 println!(Rcu64 {}, std::mem::size_of::Rcu64()); // 8 }OptionBoxT只占 8 字節(jié)這件事值得單獨(dú)說(shuō)一下。編譯器發(fā)現(xiàn)Box的指針不可能是零于是用空指針這個(gè)非法值來(lái)表示None這叫空指針優(yōu)化。這個(gè)優(yōu)化在鏈表、樹(shù)這類遞歸結(jié)構(gòu)里非常關(guān)鍵不然每個(gè)節(jié)點(diǎn)都要多帶一個(gè)字節(jié)的判別位再加對(duì)齊填充內(nèi)存占用會(huì)明顯上升。2.4 函數(shù)簽名就是一份所有權(quán)契約我一直建議新手把函數(shù)簽名當(dāng)成一份合同來(lái)讀。參數(shù)寫T表示調(diào)用方把這個(gè)值的所有權(quán)交出去了函數(shù)返回之后調(diào)用方不能再碰它寫T表示只借來(lái)讀函數(shù)內(nèi)部改不了寫mut T表示借來(lái)改借用期間調(diào)用方不能用寫self和mut self是同樣的道理只是作用在方法接收者上。一份好的簽名應(yīng)該讓調(diào)用方一眼看出“我還能不能用這個(gè)變量”。fn consume(s: String) - usize { s.len() } // 拿走所有權(quán) fn inspect(s: str) - usize { s.len() } // 只借用讀 fn append(s: mut String, tail: str) { s.push_str(tail); } // 借用改 fn create() - String { String::from(new) } // 交出所有權(quán)這四行基本覆蓋了九成場(chǎng)景。我踩過(guò)的一個(gè)坑是函數(shù)參數(shù)寫成String但其實(shí)只讀一下長(zhǎng)度結(jié)果調(diào)用方每次都得 clone 一份才能傳進(jìn)去。改成str之后String和字符串字面量都能直接傳調(diào)用方省掉了所有 clone。這個(gè)改動(dòng)看起來(lái)小在一個(gè)熱路徑上能省掉可觀的分配次數(shù)。3. 借用檢查器到底在檢查什么3.1 共享不可變、獨(dú)占可變借用規(guī)則只有一句話任意時(shí)刻你要么擁有多個(gè)不可變引用要么擁有一個(gè)可變引用兩者不能同時(shí)存在。另外所有引用必須始終有效。這條規(guī)則的動(dòng)機(jī)有兩個(gè)層次。淺層是為了防止數(shù)據(jù)競(jìng)爭(zhēng)多個(gè)線程同時(shí)讀是安全的只要有寫就必須獨(dú)占。深層是為了防止同一份數(shù)據(jù)在讀取過(guò)程中被別處改掉導(dǎo)致讀到的內(nèi)容前后不一致。舉一個(gè)最典型的例子遍歷的同時(shí)修改集合fn main() { let mut v vec![1, 2, 3]; for x in v { if *x 2 { v.push(4); // 報(bào)錯(cuò) E0502 } } }編譯器會(huì)告訴你v已經(jīng)被不可變借用不能再作為可變借用。這個(gè)限制在 C 里是允許的代價(jià)是push可能觸發(fā)重新分配原來(lái)的迭代器變成懸垂指針接著就是未定義行為。Rust 直接把這條路堵死。正確的寫法是先收集要改的內(nèi)容循環(huán)結(jié)束后再統(tǒng)一改fn main() { let mut v vec![1, 2, 3]; let need_push v.iter().any(|x| x 2); if need_push { v.push(4); } }這種“先讀后寫”的拆分模式我用了無(wú)數(shù)次幾乎所有的借用沖突都能用這個(gè)思路化解。它看起來(lái)多寫了一行實(shí)際上是把原本隱藏的時(shí)序依賴顯式化了代碼反而更清楚。3.2 NLL 讓借用的結(jié)束點(diǎn)變聰明了早期的 Rust 用詞法作用域判斷借用何時(shí)結(jié)束只要變量還在作用域里借用就算沒(méi)結(jié)束于是很多寫法通不過(guò)。從 2018 edition 開(kāi)始默認(rèn)啟用非詞法生命周期NLL借用的有效期縮短到“最后一次使用”為止。這個(gè)改進(jìn)影響巨大很多以前必須用花括號(hào)強(qiáng)行劃作用域的代碼現(xiàn)在可以直接寫。fn main() { let mut data vec![1, 2, 3]; let first data[0]; println!({}, first); // first 的最后一次使用 data.push(4); // 現(xiàn)在合法了借用已經(jīng)結(jié)束 println!({:?}, data); }這段代碼在老版本會(huì)報(bào)錯(cuò)因?yàn)閐ata的可變借用和first的不可變借用被認(rèn)為在同一個(gè)作用域里共存。NLL 之后編譯器看出first在println之后就沒(méi)用了借用提前結(jié)束后面的push就不沖突了。理解這一點(diǎn)很重要它意味著你不需要為了繞開(kāi)借用檢查而寫一堆莫名其妙的花括號(hào)只要讓借用自然地在最后一次使用處結(jié)束就行。3.3 生命周期標(biāo)注不延長(zhǎng)壽命只是描述關(guān)系生命周期這個(gè)詞嚇退過(guò)不少人其實(shí)它的作用被嚴(yán)重夸大了。生命周期標(biāo)注不會(huì)讓任何值的存活時(shí)間變長(zhǎng)或變短它只是告訴編譯器“這幾個(gè)引用之間的存活關(guān)系是這樣的”方便編譯器做檢查。真正決定值活多久的永遠(yuǎn)是它所在的作用域。最經(jīng)典的例子是返回兩個(gè)字符串切片里較長(zhǎng)的那個(gè)fn longesta(x: a str, y: a str) - a str { if x.len() y.len() { x } else { y } }不寫標(biāo)注的話編譯器報(bào) E0106因?yàn)樗鼰o(wú)法確定返回的引用到底跟著x還是y活。a的意思是返回值的存活時(shí)間不會(huì)超過(guò)x和y中較短的那個(gè)。這是一個(gè)上界約束不是延長(zhǎng)。調(diào)用方拿到返回值之后只要保證在x和y都還活著的時(shí)候用它就行。生命周期省略規(guī)則有三條記住這三條能省掉大部分手寫標(biāo)注。第一每個(gè)引用參數(shù)各自獲得一個(gè)獨(dú)立的生命周期參數(shù)。第二如果只有一個(gè)輸入引用參數(shù)那么輸出的生命周期全部等于它。第三如果有self或mut self那么輸出的生命周期全部等于self的。第三條是方法簽名的常用規(guī)則所以大多數(shù)方法不需要手寫生命周期標(biāo)注。3.4 結(jié)構(gòu)體持有引用必須寫生命周期這是新手最容易卡住的地方。結(jié)構(gòu)體里如果放了引用就必須給結(jié)構(gòu)體加生命周期參數(shù)因?yàn)榫幾g器需要確保這個(gè)引用比結(jié)構(gòu)體本身活得久。否則結(jié)構(gòu)體還存在的時(shí)候它指向的數(shù)據(jù)可能已經(jīng)被釋放了。struct Tokena { text: a str, line: usize, } impla Tokena { fn len(self) - usize { self.text.len() } }Tokena讀作“這個(gè) Token 的有效期不能超過(guò)a”。這意味著任何持有Token的地方那個(gè)被引用的字符串也得活著編譯器會(huì)一路向上檢查。這個(gè)傳播有時(shí)候會(huì)很煩一個(gè)底層結(jié)構(gòu)加了生命周期上面三層都得跟著加。我的處理策略是分場(chǎng)景的。如果這段數(shù)據(jù)是短命的、臨時(shí)的、解析完就用完的那就老老實(shí)實(shí)加生命周期零拷貝最快。如果這段數(shù)據(jù)要被存起來(lái)、跨函數(shù)傳遞、或者放進(jìn)集合里長(zhǎng)期持有那就直接存String用一次分配換掉整條鏈上的生命周期標(biāo)注。這個(gè)取舍在下一節(jié)的實(shí)戰(zhàn)案例里會(huì)詳細(xì)展開(kāi)。4. 智能指針編譯期賬本不夠用的時(shí)候4.1 Box、Rc、Arc、RefCell 各自解決什么問(wèn)題所有權(quán)的默認(rèn)模型是單一所有者加獨(dú)占可變這個(gè)模型覆蓋了大部分場(chǎng)景但確實(shí)有幾類需求它表達(dá)不了需要在堆上分配且大小在編譯期未知的遞歸類型、需要多個(gè)所有者共享同一份數(shù)據(jù)、需要在只有不可變引用的前提下修改內(nèi)容。這三種需求分別對(duì)應(yīng)Box、Rc/Arc、Cell/RefCell。類型所有權(quán)模型線程安全運(yùn)行時(shí)開(kāi)銷典型場(chǎng)景BoxT獨(dú)占堆分配取決于 T一次分配遞歸結(jié)構(gòu)、trait 對(duì)象RcT共享非原子計(jì)數(shù)否每次克隆加減一單線程共享只讀數(shù)據(jù)ArcT共享原子計(jì)數(shù)是T: SendSync原子操作比 Rc 慢多線程共享CellT內(nèi)部可變按值替換否幾乎為零小 Copy 類型的可變狀態(tài)RefCellT內(nèi)部可變運(yùn)行時(shí)借用檢查否借用標(biāo)志位增減需要在 self 里改內(nèi)容選型的順序我一般是這樣的先問(wèn)是不是遞歸類型或需要 trait 對(duì)象是就上Box再問(wèn)是不是真的需要多個(gè)所有者如果只是讀取共享用Arc包只讀數(shù)據(jù)就夠了別急著上RefCell最后才問(wèn)是不是需要在不可變引用下修改需要才用RefCell。很多人一上來(lái)就寫RcRefCellT其實(shí)八成場(chǎng)景用RcT或者干脆傳引用就能解決白白引入了運(yùn)行時(shí)開(kāi)銷和 panic 風(fēng)險(xiǎn)。4.2 Rc 加 RefCell 的代價(jià)具體在哪RcT的每次clone都要對(duì)引用計(jì)數(shù)做一次加一每次drop做一次減一減到零才釋放。這些操作在單線程里是普通的整數(shù)加減開(kāi)銷很小但不為零。RefCellT則維護(hù)一個(gè)借用計(jì)數(shù)器borrow()時(shí)檢查當(dāng)前有沒(méi)有可變借用有就 panicborrow_mut()時(shí)檢查計(jì)數(shù)器是不是零不是零也 panic。這兩個(gè)檢查都是運(yùn)行時(shí)分支編譯器沒(méi)法優(yōu)化掉。更需要注意的是循環(huán)引用導(dǎo)致的內(nèi)存泄漏。兩個(gè)Rc互相指向引用計(jì)數(shù)永遠(yuǎn)不會(huì)歸零內(nèi)存就漏了。標(biāo)準(zhǔn)解法是把其中一個(gè)方向改成Weakuse std::cell::RefCell; use std::rc::{Rc, Weak}; struct Node { value: i32, next: OptionRcRefCellNode, prev: OptionWeakRefCellNode, // 用 Weak 打破環(huán) } fn main() { let a Rc::new(RefCell::new(Node { value: 1, next: None, prev: None })); let b Rc::new(RefCell::new(Node { value: 2, next: None, prev: Some(Rc::downgrade(a)) })); a.borrow_mut().next Some(Rc::clone(b)); println!(a 的強(qiáng)引用數(shù): {}, Rc::strong_count(a)); println!(a 的弱引用數(shù): {}, Rc::weak_count(a)); }Weak不增加強(qiáng)引用計(jì)數(shù)升級(jí)成Rc的時(shí)候要調(diào)upgrade()返回Option因?yàn)槟繕?biāo)可能已經(jīng)被釋放了。這個(gè)模式在雙向鏈表、樹(shù)結(jié)構(gòu)里都會(huì)用到我建議只要結(jié)構(gòu)里出現(xiàn)“指回去”的邊就默認(rèn)用Weak不要等到內(nèi)存漲上去才回頭改。4.3 有時(shí)候該退一步換數(shù)據(jù)結(jié)構(gòu)而不是堆智能指針這是我踩過(guò)的最大的一個(gè)坑。早期寫一個(gè)圖結(jié)構(gòu)的處理邏輯習(xí)慣性地用RcRefCellNode表示每個(gè)節(jié)點(diǎn)節(jié)點(diǎn)之間互相引用。代碼能跑但性能很差而且一旦涉及并發(fā)就完全沒(méi)法用因?yàn)镽c根本不是Send。后來(lái)改成用VecNode存所有節(jié)點(diǎn)節(jié)點(diǎn)之間用usize索引互相引用性能提升非常明顯代碼也短了。struct Graph { nodes: VecNode, } struct Node { edges: Vecusize, // 索引而不是引用 }索引方案的代價(jià)是你得自己保證索引有效刪節(jié)點(diǎn)的時(shí)候要處理懸空索引。但它換來(lái)的是連續(xù)的堆布局、零引用計(jì)數(shù)開(kāi)銷、天然的Send Sync而且序列化也簡(jiǎn)單得多。我現(xiàn)在的判斷標(biāo)準(zhǔn)是如果一個(gè)數(shù)據(jù)結(jié)構(gòu)里RcRefCell出現(xiàn)超過(guò)兩處就該停下來(lái)想想是不是該用索引或者 arena 了。5. 一個(gè)真實(shí)場(chǎng)景的重構(gòu)從編譯不過(guò)到跑得穩(wěn)5.1 需求解析文本并緩存字段假設(shè)要寫一個(gè)小模塊從多行文本里解析出鍵值對(duì)緩存起來(lái)供后續(xù)查詢。第一版我圖省事直接讓結(jié)構(gòu)體持有輸入的切片struct Configa { entries: Vec(a str, a str), } impla Configa { fn parse(input: a str) - Self { let mut entries Vec::new(); for line in input.lines() { if let Some((k, v)) line.split_once() { entries.push((k.trim(), v.trim())); } } Config { entries } } fn get(self, key: str) - Optiona str { self.entries.iter().find(|(k, _)| *k key).map(|(_, v)| *v) } }這段代碼能編譯get返回的引用直接指向原始輸入零拷貝速度很快。問(wèn)題出在調(diào)用方那邊一旦把input的所有權(quán)交出去或者input是函數(shù)內(nèi)部臨時(shí)構(gòu)造的String就出事了。5.2 第一版在真實(shí)調(diào)用鏈里崩了調(diào)用方大概是這樣的fn load() - Configstatic { let content std::fs::read_to_string(config.txt).unwrap(); Config::parse(content) // 報(bào)錯(cuò)返回引用了局部變量 }編譯器報(bào) E0515說(shuō)不能返回指向局部變量的引用。這不是編譯器的刁難content在函數(shù)結(jié)束時(shí)就 drop 了返回的Config里那些指針會(huì)立刻變成懸垂指針。如果這段代碼在 C 里寫編譯能過(guò)運(yùn)行時(shí)讀到的就是垃圾數(shù)據(jù)而且可能好幾個(gè)月都不出問(wèn)題直到某次內(nèi)存布局變化才突然炸。第二版我把結(jié)構(gòu)體改成持有Stringstruct Config { entries: Vec(String, String), } impl Config { fn parse(input: str) - Self { let mut entries Vec::new(); for line in input.lines() { if let Some((k, v)) line.split_once() { entries.push((k.trim().to_string(), v.trim().to_string())); } } Config { entries } } fn get(self, key: str) - Optionstr { self.entries.iter().find(|(k, _)| k key).map(|(_, v)| v.as_str()) } }這樣寫能跨函數(shù)傳遞、能存進(jìn)集合、能放進(jìn)Arc里共享代價(jià)是每個(gè)鍵值對(duì)兩次堆分配。對(duì)于配置文件這種一次性加載、長(zhǎng)期駐留的場(chǎng)景這個(gè)代價(jià)完全值得。但如果是解析大文件做流式處理每行兩次分配就有點(diǎn)浪費(fèi)了。5.3 第三版用 Cow 做折中Cow寫時(shí)克隆是這兩者之間的折中方案。它在不需要修改的時(shí)候借用原始數(shù)據(jù)需要修改的時(shí)候才分配use std::borrow::Cow; enum Entrya { Borrowed(a str), Owned(String), } fn normalize(s: str) - Cow_, str { if s.contains(\t) { Cow::Owned(s.replace(\t, )) } else { Cow::Borrowed(s) } }Cowa, str是標(biāo)準(zhǔn)庫(kù)提供的枚舉只有Borrowed和Owned兩個(gè)變體。它的好處是調(diào)用方不用關(guān)心底層到底是借用還是擁有用.as_ref()或Deref就能當(dāng)str用。壞處是它仍然帶著生命周期參數(shù)跨函數(shù)邊界的時(shí)候該傳播還得傳播而且枚舉本身占的??臻g比單純的str大具體多大可以用size_of實(shí)測(cè)一下不同版本和優(yōu)化下會(huì)有差異。我現(xiàn)在的選擇順序是數(shù)據(jù)生命周期短、調(diào)用鏈淺用str加生命周期數(shù)據(jù)要被長(zhǎng)期持有、跨線程傳遞用String兩者之間搖擺不定的中型場(chǎng)景用Cow。這個(gè)順序不是教條但你照著走能少走彎路。6. 高頻報(bào)錯(cuò)與排查速查6.1 錯(cuò)誤碼對(duì)照表被借用檢查器攔住的時(shí)候先看錯(cuò)誤碼再看提示里的“誰(shuí)的借用還沒(méi)結(jié)束”。下面這張表是我整理的高頻錯(cuò)誤基本上覆蓋了日常八成的情況。錯(cuò)誤碼含義典型改法E0382使用了已經(jīng) move 的值改傳引用或在轉(zhuǎn)移前 cloneE0499同一作用域內(nèi)兩次可變借用拆分成兩個(gè)階段或用索引代替引用E0502可變借用與不可變借用沖突先讀后寫或縮短不可變借用的生命周期E0505借用還沒(méi)結(jié)束就要 move讓借用先結(jié)束再 moveE0515返回了局部變量的引用返回?fù)碛兴袡?quán)的類型E0597被借用的值活不到那么久調(diào)整作用域順序或改為擁有E0716臨時(shí)值在借用期間被釋放先用 let 綁定成變量再借用E0106缺少生命周期標(biāo)注按省略規(guī)則補(bǔ)上或改成擁有類型E0716 值得單獨(dú)提一句很多人寫過(guò)類似的代碼然后一臉茫然fn main() { // let s String::from(hello).as_str(); // 報(bào)錯(cuò) E0716 let tmp String::from(hello); // 先綁定成變量 let s tmp.as_str(); // 再借用 println!({}, s); }原因是String::from(hello)產(chǎn)生的臨時(shí)值在這一行結(jié)束時(shí)就被 drop 了as_str()借出來(lái)的引用立刻懸垂。先綁定到tmp之后tmp活到作用域結(jié)束借用才合法。這類問(wèn)題的排查思路很統(tǒng)一看那個(gè)被借用的值是不是臨時(shí)值是就給它一個(gè)名字。6.2 排查順序先找誰(shuí)借了誰(shuí)再看誰(shuí)要活多久我處理借用錯(cuò)誤的固定流程是這樣的。第一步看錯(cuò)誤提示里點(diǎn)名的變量確認(rèn)是“值被 move 了”還是“借用沖突”。第二步如果是借用沖突從報(bào)錯(cuò)位置往上找找最后一個(gè)使用這個(gè)引用的地方那里就是借用結(jié)束的位置。第三步如果想讓借用提前結(jié)束就把后面的寫操作挪到那之后或者把讀的結(jié)果先取出來(lái)存成獨(dú)立的值。第四步如果怎么調(diào)都不行說(shuō)明數(shù)據(jù)結(jié)構(gòu)的所有權(quán)模型設(shè)計(jì)有問(wèn)題考慮換成索引、Rc或者擁有類型。這個(gè)流程里第三步最常用。舉一個(gè)我經(jīng)常遇到的場(chǎng)景需要在HashMap里查一個(gè)值然后修改它use std::collections::HashMap; fn main() { let mut map: HashMapString, i32 HashMap::new(); map.insert(a.to_string(), 1); // let v map.get(a).unwrap(); // map.insert(b.to_string(), 2); // 報(bào)錯(cuò) E0502 // println!({}, v); let v map.get(a).copied().unwrap_or(0); // 先取值結(jié)束借用 map.insert(b.to_string(), 2); println!({}, v); }copied()把Optioni32變成Optioni32借用當(dāng)場(chǎng)結(jié)束后面的插入就自由了。這個(gè)技巧在處理哈希表、緩存的時(shí)候特別好用我基本養(yǎng)成了習(xí)慣只要借出來(lái)的值很小且 Copy先拷貝再用。6.3 幾條踩出來(lái)的實(shí)操心得第一別怕加花括號(hào)。雖然 NLL 已經(jīng)聰明很多但在某些復(fù)雜表達(dá)式里顯式劃一個(gè)作用域讓借用提前結(jié)束比絞盡腦汁調(diào)整順序省事得多。第二clone()不是洪水猛獸在冷路徑上用 clone 換代碼清晰度是完全劃算的我反對(duì)的是在熱循環(huán)里無(wú)意識(shí)地 clone。第三遇到RcRefCellT的borrow_mutpanic先找有沒(méi)有在同一段代碼里同時(shí)持有兩個(gè)借用尤其是鏈?zhǔn)秸{(diào)用里臨時(shí)值還沒(méi)釋放的情況把中間結(jié)果用let綁定出來(lái)往往就好了。第四函數(shù)簽名優(yōu)先用借用只有在確實(shí)需要保存或跨線程的時(shí)候才用擁有類型這條規(guī)則能讓你的模塊接口干凈很多。第五如果一段邏輯里到處都是unsafe或者反射式的類型轉(zhuǎn)換那多半不是所有權(quán)的問(wèn)題是數(shù)據(jù)結(jié)構(gòu)選錯(cuò)了回頭看看第 4.3 節(jié)。關(guān)于內(nèi)存管理我個(gè)人在實(shí)際操作中最深的一點(diǎn)體會(huì)是所有權(quán)系統(tǒng)真正改變的不是你寫代碼的語(yǔ)法而是你設(shè)計(jì)數(shù)據(jù)結(jié)構(gòu)的方式。寫 C 的時(shí)候我會(huì)自然地想“這塊內(nèi)存誰(shuí) free”寫 Java 的時(shí)候基本不想寫 Rust 之后我會(huì)在動(dòng)手寫第一行之前就想清楚“這個(gè)值的生命周期有多長(zhǎng)、誰(shuí)能改它、要不要共享”。這個(gè)思考前置的過(guò)程一開(kāi)始很別扭習(xí)慣之后反而省掉了大量調(diào)試時(shí)間因?yàn)楹芏鄦?wèn)題在敲代碼的時(shí)候就已經(jīng)被逼著想明白了。
返回列表
PREV
查看更多資訊
NEXT
返回資訊列表
自拍鲍鱼一区在线高清观看免费| 日日A∨| 久久夜夜| 久草毛片| 亚洲欧美精品久| 二色av| 国产成年精品高清在线观看91| 日韩AV噜噜噜一区二区三区四区| 天天躁夜夜躁狠狠躁AV| 亚洲欧洲色情高清| 国产超碰在线一区| 久久9亚洲| 99热精品在线在线| 中文字幕亚洲在线一区 | 操人妻丝袜高跟| 久久‘黄片视频| 亚洲中文电影| AV色女综合| 蜜臀99久久精品久久久懂爱| 色九色久| 超碰这里有精品| 蜜桃臀 后入 一区 二区 三区 在线| 色爱三区| 九九黄色网| 国产精品香蕉热久久新品| 欧美五十路熟| 免费a级毛片av无码久久精品中文字幕| 99久草| 日韩av电影网站| 9精品久久| 中文字幕-区二区三区四区视频中国| 无码色| 九九色婷婷| 国产真实野战在线视频| 麻豆国产免费影片| 第一高清av中文字幕| 日韩欧美大力操| 激情五月综合开心五月| 伊人精品久久网站| 操逼无码一区| 手机看片1024你懂的国产| 91碰超| 午夜寂寞欧美| 国产激情视频在线观看| 大香网伊人久久综合| 免费看欧美美女黄色大片 | 婷婷日韩一区二区三区中文字幕在线| 午夜情侣自拍网站| 国产婷婷一区| 四虎影视永久在线观看精品免费网站| 久久久成人免费av电影| 78m啪啪啪| 大香蕉草草| 欧美激情专区| 国产美女裸体秘 永久无遮挡| 成人性爱免费播放| 日本操嫩b网| 婷婷丁香五月天综合东京热| 欧美色色色| 日韩另类色图| 大肉棒导航| 日本精品加勒比海一区| 中国AAAAAA黄色片| 国产精品久久伊人| 白丝少妇一区二区| 亚洲天堂电影网99999| 97中文字幕九区| 精品一区二区三区免费古装毛片香港三级日本三级人妇 | 手机不卡视频不卡在线一二三区 | 99国产在线 精品 视频| 久久久一级| 97激情97激情| 美女爽到高潮91| 日韩熟女无码| 日本超碰在线国产一区| 在线情色电影 91大 | 风流老熟女一区二区三区l| 久久丁香五月天| 东北夫妻性偷拍| 亚洲精品蜜桃久久久久久久| 亚洲精品欧洲色| 香蕉国产精品麻豆亚洲欧美日韩| 在线国产一区二区av| 奸色色 男人天堂 天天射| 亚洲第一二区另类图| 99rre在线精品99re8| 欧美日韩啪啪电影| 欧美黑人猛交春色影视大全| 乱色老一区二区三区的观看方式 | 天天看综合网| 欧美日韩亚洲少妇寂寞影院正在播放 | 樱花蜜乳av| 精品人妻伦一二三区久久| 青青草黑寡妇男人天堂| 国产精品农村妇女| 久久久精品无码亚免费| 91色色综合| 国产色产精品在线观看| 天天干少妇| 人妻熟妇久草在线| 新久久AV| 欧美色图成人网一区二区 | AV九九| 99久在线精品99re8热视频在线| 精品久久久av无码免费| 色五月婷婷五月天| 久久久亚洲熟妇资源| 白天啪啪晚上啪啪视频| 乱老熟女一区二区三区| 精品成人无码| 一区二区视频你懂的| 亚洲色狠| 区一在线观看| 肏逼福利网站| 亚洲限制级| 插入逼91| 性生活无遮挡纯毛片在线看| 欧美天天干| 午夜啊啊啊| 亚洲欧洲自拍图片专区满春格| 91亚洲黑人| 欧美亚洲手机在线| 成人在线视频一区| 麻豆这里只有精品| 97视频网站| 中文伊人大香蕉视频| 中日韓欧美高清| 超碰碰碰碰| 超碰99在线| 亚洲日韩一区电影| 天美传媒精品一区二区| 久热精品色情| 日本熟女免费視颖| 视频在线中文字幕| 97久久超碰| 欧美精品庄| 人夜夜精品网站香蕉嫩草| 亚洲成人ab| 蜜桃精品一区二区三区ww| 另类图片综合| 天天插夜夜爽| 成人短视频在线观看| 日躁天天爽爽| 精品一久久久| 国模少妇一区二区三区| 欧美色图色综合| 神马午夜久久久| 少妇干B| 97鸡把在线视频| 国产欧美伊人| 操逼啊啊啊91| 精品午夜福利| 超碰色大香蕉| 蜜臀AV成人精品蜜臀| 自拍偷拍 高清无码| 欧美啪啪天堂| 日本一二三高清| 影音先锋视频在线| 男女做爰猛烈动高潮A片免费应用| 久久久久久久国产| 日韩精品一二三四| 在线强奷到舒服的无码视频| 一级一性爱免费视频| 亚洲精品1区| 一区二区 韩日AV| 精品中文字幕第一页| 高颜值美女口爆高潮浪叫| 嗯嗯,啊啊,国产精品| 午夜福利免费精品视频| 欧美日产国产在线成人第一区| 91久热| 成人精品视频一区二区| 先锋精品av色鲁| 91人妻素女| 日本精品999| 亚洲 欧美 日本 国内 首页| 9久久美女首页| 亚洲 日韩 欧美 国产综合体| 最新无码国产| 久久精品久久久久久久| 日韩内| 中 文字幕一区二区三四 五 区日 日 骚| 1769精品一区二区三区| 欧美视频一区二区在线| 91成人在线免费视频| 凹凸视频在线一区二区| 清纯唯美综合| 亚洲欧美激情小说| julia ann久久| 日欧毛片久久| 久久精品人妻一区二区| 日日A∨| 久久久不能久久久久| 99色在线视频| 偷拍精品一区二区三区| 97亚洲资源| 91成人在线免费视频| 26uuu欧美日韩| 欧美黑人熟妇精品91| 人妻无码一区二区三区久久99| 99爱爱| 91丝袜在线观看| 青青草依人大香蕉| 成人草草视频| 精品少妇高潮久久| chaopen97久久| 久久骚| 久久一本大香蕉| 97自拍一区| 99re69综合| 国产天天看| 艳尻美人妻| 蜜桃在线观看一区二区三区 | 久久直播国产| 日本免费人成视频播放120秒| 91老司机视频| 国产第25页在线观看| 琪琪精品免费一区二区三区| 国产91乱伦| 人人操人人干网页| 欧美视频边做饭边橾| 亚洲最新av无码成人精品区| 人妻中文字幕日韩电影| 天天操天天舔| 青青草操逼逼视频| 亚洲av总站| 99热在线不卡| 欧美洲精品一级| 97精品人妻一二三四| 人妻 欧美亚洲| 久久九九97| 麻豆天美91| 国产操逼视频在线观看| 东亚亚洲无码高清| 91N欧美| 天色综合网| 老女人91| 成年人黄色| 人人操人人爽人人操人人| 呦呦影院| 亚洲欧洲网站免费观看| 欧美中文字幕男人天堂久久精品| 91性生活久久久| 大但人体久久久久| AVE乱伦| 人妻素股| 国产亚洲日本精品在线| 91麻豆天美国产欧美| 91人妻超碰| 亚洲天堂日本| 亚洲乱妇p22| 亚洲精品国产熟女久久久久久| 亚洲一区二区性爱电影| 久久久久中出| 久久精品无码熟妇一区二区三区视频导航| 一区二区影视| 国产久久av| 青青草中文-久久青草精品一区二区三| 国产久久视频| 麻豆精品.欧美精品.日韩精品.| 视频一区二区三区精品| 能看的av| 欧美亚州综合网图片| 欧美国产精品| 伊人久久亚洲中文字幕| 亚洲色图欧美色图在线播放| 丝袜人妻av一区二区| 国产97视频免费观看| 日韩少妇丰满亚洲| 大香蕉综合网| 日本在线不卡一二区| 91欧美美女日韩国产婷婷| 中文字幕丝袜| 激情丁香五月婷婷| 国产精品伦理| 五月婷婷无码| 欧美天天影院| 亚洲欧洲综合视频在线| 亚洲中亚日激情视频| 在线观看不卡一区二区三区| 日韩女优中文字幕| 97精品网| 女人的久久久| 九九九免费视频| 亚洲1区| 992大香蕉| 亚洲欧洲综合视频在线| 天堂av最新电影网| 小情侣高清国产在线视频| 性老妇一区二区三区| 欧美91精品国产自产| 亚洲AV免费在线| 天天天操天天天爱| 国产亚州高清国产拍精| 精品国产久久乱码| 国产一区二区三区影片| 另类图片五月天| 思思热影视| 91色人| 久久老子无码午夜伦不卡| 久久久久久九九九九九九| 天天摸夜夜添无码小视频| www.高清无码诱惑一区.com | 免费看黄视频亚洲网站| av线电影| JULIA一区二区三区在线播放| 精品综合久久久久久97| 国产一区二区啪啪视频| 婷婷性网| 亚洲黄日韩无码专区| 欧美色www亚洲国产阿娇要播| 刺激性视频黄页| 呦呦影院| 亚洲一区制服诱惑| 裸体美女免费看网站青草| 亚洲久久久| 男人的天堂.com| www.yeyecao| 欧美色图在线视频少妇| 日本色婷婷| 亚洲影院成人| 欧洲精品欧洲精品| 熟女在线视频| 看日韩操逼| JuliaAnn丝袜熟女系列| 亚码人妻| 亚洲天堂,男人| 国产精品美女久久久久久网站| 少妇与黑人高潮在线| 亚洲成人无码影院| 欧美色视| 9997se| 97视频网站在线观看| 成人乱人伦一区二区| 午夜视频久久久| 亚洲综合另类欧美久久久| 95自拍视频在线观看| 国产中午字一暮区| 97这里都是精品| 国产无套粉嫩白浆在| 中国人高清www色视频免费| 神马久久69| 天天日老熟妇| 久久艹逼视频| 一区二区三区成人高清视频| 久久春色| 欧美日韩在线小说| 尤物AV免费网站| 99国产在线绯色一区| 妺妺跟我一起洗澡没忍住| 一级岛国大片| 超碰九7| 日韩av情韩国爱禁区av一区二区| 亚洲不卡不卡中文字幕不卡| 色五月婷婷色| 亚洲国产高清福利视频| 级做a爱无码性色永久免费| av激情亚洲五月天| 午夜国产综合视频在线观看 | 清纯唯美亚洲另类| 91N综合网在线| 六月丁操逼| 人妻熟女午夜精品在线| 首页中文字幕中文字幕免费| 日韩性爱毛片操骚逼| 丰满熟女一区二区三区在线播放| 99精品九九九九九九| 后入式视频国产自| 日日干男人的天堂| 97AV在线免费观看| 久久久av爱| 不卡码视频| 伊人影院中文字幕| 正在播放:深夜激情大战,自带黑丝袜全力输出骚穴 | 91精品久久久久久77777| 久久国色天香香蕉| 野狼激情网| 丁香五月av| 五月天婷婷基地| 日韩国产中文字幕| 国内精品伊人久久久久影院会| 中文字幕一区二区韩| 久久久久久人妻一区精品色欧美| 国内精品嫩模A∨私拍小视频| 91人人| 久久一区二区蜜桃| 天天草天天日| 国产兽交视频在线播放| 国产亚洲美日韩Aⅴ中文字幕无码成人| 立川理惠被中出无码| 大香蕉一级黄色片久久| 欧美高清无码免费视频高清版| 羞涩视频| 福利操逼| 久久 国产精品 一区| 亚洲精品美女久久久久久久久| 26uuu国产免费观看| WWW黄片COM| 综合久久婷婷| 岛国小电影| 91美女视频在线| 亚av顶级裸体一区二区三区四区五区| 天天影视之亚洲综合网| 狠狠爱大香蕉| 涩综合导航| 日本东京热加勒比久久| 大香蕉久操| 人夜夜精品网站香蕉嫩草| 后入人妻一区| 国产99999久久精品| 日韩欧美中文字幕搭讪巨乳美人妻视频| 97日韩超碰超碰中文字幕| 亚洲欧美综合| 亚洲成?V人片在线观看福利| 人妻精品一区二区| 高清有码一区二区| 国产精品视频麻豆入口| 无遮挡h肉动漫在线观看| 五月天婷婷小说| 四月丁香婷婷| 日日碰视频网| 综合激情二| 牛牛aV| 亚洲91av| 夜色97| 天天综合网网欲色| 影音先锋中文字幕日本好一区二区| 99婷婷| 日韩美女高潮喷水视频| 天美传媒AV在线| 日韩性爱1级片视频| 99性视频| 亚洲天堂美臀在线| 亚洲精品久久久久毛片A片拉屎| 99老司机精品视频在线观看| 婷婷情色综合网| 久久人妻一区二区三区高清| 看日韩黄片| 无码少妇精品一区二区60岁老人| 人妻少妇三级| 欧美18老人禁| 青青草日本无码| 哑洲在线| 免费自拍三级综合| 秋霞男人网| 青娱乐妇女性生活| 久久草在线综合视频| 18岁禁 茉莉成人久久| 日韩在线电影| 一区二区你上我| 久久久九九| 无码天天操| 欧美少妇第一页| 欧美色图91| 日韩成人大片在线观看| 久超碰这里只有精品| 亚洲综合另类小说色区亚洲成av人片在www | 精品大全99999| 人干人人人操人人摸| 亚洲情色1区| 超碰97护士| 香蕉久久国产AV一区二区| 伊人四虎综合| 天天干天天狼在线视频| 久欲AV| 91成人久久 | 青娱乐福利99| 麻豆国产成人精品| 高潮毛片无遮挡高清免费| 怡红院怡春院| 中文字幕AV乱伦| 97超碰色屌| 日韩偷拍一区二区三区| 激情五月天视频| 国内三级自拍小视频在线观看| 欧美日韩亚洲高清不卡一区二区三区| 天堂成人网| 日日日日日| 欧美碰碰综合色| www.婷婷六月天| 人妻丝袜一区二区三区在线| 人妻加勒比东京热| 久久久久久久强迫| 国产精品色哟哟| 人妻干天天| 情色五月天网| 一区三区啪啪| 偷拍五区| 欧美一级国产一级| 亞洲久久直播| 国产亚洲日本精品在线| 久久久久深夜无码| 欧美日韩91| 青娱乐黄色录像| 欧美激情总合网| 搡老女人911熟妇老熟女| 九九玖玖精品| 狼狼色丁香久久婷婷综合五月 | 欧美久久人妻少妇一区二区| 天天干天天狼在线视频| 九九九九精品视频| 91色综合激情| 一区二区三区机械有限公司| dy888午夜老子影视达达兔| 亚洲国产一级中文综合久久天堂在线免费观看| 爽极品影院| 青娱乐 青青青操 日逼| 女同性恋一区二区三区精品视频| 无码免费精品高清| av激情亚洲五月天| 欧美在线干| 青青草日逼视频| 凸凹视频在线观看| 在线毛片片免费观看| 亚洲av总站| 亚洲图片色图欧美另类| 美女t无毒不卡不卡| 亚洲综合888| 亚洲精品中文字幕一区在线视频| 亚洲不卡三级手机播放| 狠狠干2020| 人妻在线中出视频| 欧洲色| 亚洲一区二区三区播放在线| 人人妻人人玩人人澡人人爽| 人人摸人人舔一区二区| 成人日韩中文字幕| 色色亚洲| 日本肏逼视频在线观看| 成人免费毛片| 国产 日韩,欧美 自拍| 91高清日| 丰满人妻一区二区中文| 久久99手机免费视频| 色色色综合网| 91在线无码精品秘 软件| 日本精品中文字幕视频| 亚州欧美色图| 久久久久99精品成人片蜜臀| 婷婷九月国产| 精品一区二区三区四区外站| 狠插 制服 自拍| 国产最新AV| 婷婷97| 亚洲欧洲综合视频在线| 日韩成人性爱AV| 天天激情干| 豆花视频操逼网址| 国产91av在线播放| 五月天婷婷在线看| 亚洲一区二区三区春色| 日韩啊V| 天天澡天天爽日日AV| 欧美一级二级三级| 日韩超碰97| 熟女人妻一区二区三区免费看 | 不卡av在线中文字幕| 百度百度日本操逼| 乱伦一二三| 黄色成人网久久久久久| 香蕉国产精品麻豆亚洲欧美日韩| 五月丁香黄色网| 黄片视频观看| 无码一区二区精品视频久久久春药| 国产一区二区三区高清视频| 日本性爱视频一级| 日本十八禁免费看污网站| 人人干黄色| 国产精品无码av嫩草| 可能人人看人人摸| 激情久久av一区av二区av| 色综合久久888| www.婷婷六月天| 欧美日韩高潮喷水91| 偷窥自拍亚洲色图| 日韩欧美丝袜诱惑| 97国产精品久久久久 | 国产亚洲精品美女久久久久久2021| 日韩人妻有码免费视频| 91天堂色男人的天堂| 九九亚洲视频| 51一区二区三区| 亚洲。日韩。欧美| 骚乳在线| 9 9无尺码天堂网| 蜜臀99久久精品| 久久久久久九九九九九| 色哟哟 日韩精品| 十八岁啪啪视频免费看| 精品人妻一区二区三区夜夜| www被窝色com| 日本一卡二区在线| 97超碰超碰| 欧美激情另类一区二区| 亚洲天堂性爱| 男人的天堂久久狠| 91第一页| 可以免费观看的日韩av毛片| 亚州精人品大香蕉| 亚洲十八禁止| 亚洲情色综合| 亚洲精品成人激情在线| 岛国AV一区二区电影| 97爱啪| 襙一襙| 久久久久9| 久久国产对白激情浪潮| 欧美劲爆第一页| 亚洲 日本 国产 综合| 日日干夜夜干| 天天操天天日青青草超碰av| 成人羞羞视频国产| 久久九九综合| 日本孕妇孕交| 亚洲乱色熟女一区| 日韩AV电影网站| 中出在线视频| 午夜激情成人在线观看| 久久啊哟| 九七毛片九九毛片| 日本高清加勒比| 国产黄色动态精品| 超碰视97中文| 国产精品高清2021在线| 九99久久| 中文字幕,人妻,日韩| 超91综合网| 桑老女人九区| 日韩av在线免费网站| 国产成人AV麻豆| 试看日韩黄片| 日韩美女久久一区二区三区| 欧美精品一二三| 天天色播亚洲综合网站| 69久久久久久久久久久久久| 午夜福利一区二区影院| 欧美狠狠弄| 凹凸视频在线一区二区| 玖玖人人爱| 91国模| 口爆综合网| 久夜视频| 国产人妻精品久久久一区二区三区 | 亚洲国产综合图区中文字幕| 99爱精品| 免费视频97| 午夜精品久久久久久久男人的天堂| 美女天天干| 久久99精品视频| 国产精品一区二区麻豆| 亚洲一区日韩| 粉嫩av一区二区三区天美传媒 | 国产99999久久精品| 欧美日韩精品一区二区三区高清| 久久99精品国产| 中文字幕精品日韩中文字幕| 天天操天天7| 五月天黄色激情视频| 日韩成人人妻网站| 丁香五月天啪啪| 大香蕉综合网| 九九十八精品| 中文字幕一区电影在线观看| 久久久精| 啊…啊…操我用力操我| 国产精品视频内谢女人| 国产精品久久久久久久久久久久久久久久久久 | 秘书高跟黑色丝袜国产91在线| 五月丁香啪啪网| 男人的天堂va| 欧美日韩国产男人| 99热这里只有精品地址| 99av| 久久精品免视看国产成人﹣蜜臀av一区. 久久精品免视看国产成人,蜜臀av一区 | 大香蕉www.超碰| 亚洲色资源| 亚洲AV无码国产成人| 9Ⅰ超碰| 91色黑人少妇| 91人妻尻屄视频| 啊啊啊啊啊啊啊啊在线观看| 91伊人影视综合| 日韩午夜精品一区二区三区电影| 国内一级精品| 亚洲国成人情色好看电影| 日韩av一级黄片| 2019天天干| 风月影院男女十八禁| 97超碰国产精品| 凹凸视频在线观看伊人| 亚洲色图亚洲| 久操视频在线| 夜夜国产一区| 一本一道人妻久久一区二区三区| 天天干干天天干干| 999精品久久久久久久| 天天综合网~91综合网| 九九热免费国产视频婷婷伊人| 国产人妖视频一区在线观看| 97超碰欧美中文字幕| 加勒比东京热五月天天堂网| 炮色五月| 99精品久久| 欧美一级久久久久久久大片动画| 国产剧情在线| 久久久久九九九九九| 99青青草国产视频| 丝袜AV一二三区| 欧美精品自慰系列寂寞少妇| 成人无码在线超碰网| 国产精品剧情| 加勒比综合在线| 亚洲999综合| 亚洲天堂自拍| 欧亚乱色熟一区二区三四区| 丝袜大香蕉| 综合操逼| 国产中文大片资源中文字幕| 国产 日韩,欧美 自拍| 精品夜夜澡人妻无码AV| 中文字幕无码不卡啪啪| 色天堂在线观看| 麻豆伊人网| 婷婷色香| 色婷婷在线视频精品导航| 加勒比大香蕉视频在线| 国产原创剧情在线丝袜 | 久久6热精品99视频| 久久內射| 色婷婷婷五月天激情四射| 东北黄色电影| 国产精品经典一卡久久久| 69精品少妇一区二区三区蜜桃| 夜夜草网站| 亚欧性爱在线无码| 欧美很很操视频| 九九黄色视频在线观看| 女人午夜视频777| 网页导航五月天免费一二三区| 免费超碰97在线观看| 亚洲中文字幕久久人妻| 欧美性爱日韩性爱| 青椒国产97在线熟女| 强奸国产在线| 成人性爱美曰韩| 亚洲福利中文字幕在线| 亚洲人妻av| 人妻啊啊人妻啊啊| 日本韩国一本产品小视频日本韩国一本产品久久久产品小视频日本韩国一本产品久 | 婷婷AV一区二区三区| 国产视频不卡在线观看| a在线视频免费观看| 97人人射| 蜜桃精品一区二区三区ww| 超碰97资源大奶| 欧美97视频| 欧洲站一级二级三级h| 欧美高清91| 亚洲色宗合| 男女做爰猛烈动高潮A片免费应用| 日韩三A大片在线观看| 思思热国产在线视频| 欧美麻豆成人同性GⅤ在线| 婷婷久草| 免费9 1久久| 人人摸人人舔一区二区| 丝袜AV一区二区三区| 国产无码久久高清| 家庭乱伦性爱av| 开心婷婷五月| 人妻一区久久二区三区色播| 亚洲欧美综合网站| 久久啊啊啊| 亚洲精品三区在线观看| 中国国国产一级特黄毛片| 开心五月天激情网| 91久久久视| 99999亚洲另类| 日韩av性爱在线播放| 久久夜黄色无码A级大片| 99久久久99久久91熟女| 久久999久| 人妻丝袜一区二区三区在线| 人人玩人人添人人澡免费| 免费视频a级毛片免费视频| 夜夜操老骚逼视频网站| 亚洲 无码 有码 中文字幕| 欧美天天射| 国产精品一级特黄aaa大片在线观看| 色五月综合网| 97资源免费视频| 性色A∨91| 国语av最新自产拍在线观看| 嗯嗯,啊啊,国产精品| 欧美日日人人天天| 免费看黄片现成| 色色99| 伊人视频| 国产操伦| 91在线视频免费中出| KK色在线影院| 草草影院日本第一页| 视频二区美腿丝袜制服人妻欧美 | 亚洲欧洲自拍图片专区满春格| 天堂种子在线www网资源| 97欧美色资源| 国产1024在线播放| 长长久久免费视频| 四虎免费在线播放| 国产操逼逼网| 亚洲在高跟鞋自慰久久在色线| 国产精品操| 亚洲夜夜欢无码一区二区| 久久久久国产| 岛国大片国产| 99在线观看无大码| 色综合一本| 日韩三四五区| 亚洲综合在线第一页| 色噜噜婷婷| 精品高清牛人盗摄一区二区三区中文字幕A片免费在线观看 | 国产精品人妻熟女aⅴ| 男人天堂站| 天天激清| 精品网站9999| 84YTCOM性无码| 亚洲色人妻综合| 69精品| 加勒比无码一区二区三区| 天天干人妻视频| 成人黑料社久久| 欧美同性恋 的搜索结果 - 91n| 九月丁香综合网| 玖玖爱综合网| 777奇米影视777四色| 97免费视频在线观看视频| 黄色电影观看久久9| 一本久久精品中文字| 激情无码日韩| 日日干夜夜骑| 亚洲天堂 视频你懂的| 极品出轨视频网站| 99久热| 97超碰超碰| 麻豆九九九| 一级日本牲交大片好爽在线看| 久久999久| 操B在线观看| 欧美色图另类图片| 人妻天堂综合网| av毛片aaaaa免费看| 啊啊啊啊二区好大| 国产一级操B视频| 大白逼三四级| 欧美夜夜狠| 日韩精品在线放| 亚洲成人妻日韩在线| 国产浮力影院第1页| 91操熟女视频| 亚洲熟女国产综合另类| www.久久制服糖| 久久偷偷色综合蜜桃| 婷婷丁香六月| 成人五月天丁香激情综合| 亚洲天堂情色| 中日高清无码操逼视频| 天天看片青娱乐| 大香蕉伊人在线成人AV在线观看 | 亚热日本熟女| 99自拍视频在线| 一起草三级AV电影在线观看 | 人妻天天夜夜爽一区二区| 国产精品一区二区手机看片| 超碰久久网| 久久怡红院| 国产精品久久久久久久电影渣男| 屁股久久久久久久久| 丁香激情五月| 国产最新小视频在线播放下载 | 综合熟女| 人人操人人干网页| 97天天操| 99热大香蕉伊在线| 午夜天天碰综合视频| 大香网站| 秋霞一集毛片观看| 亚洲熟女乱综合一区二区在线-...亚洲国产日韩欧美一区二区三区,久久久久久精 | 欧美日韩少妇色情| 国产成人+综合亚洲+天堂| 成人无码在线视频网站| 蜜臀Av一区二区三区| 91艹逼精品| 少妇一线天久久久久久| 日韩国产乱子伦App| 久久超碰网| 一本色道久久综合亚洲二区三区| 日韩精品人妻中文字幕有码午| 精品久久人妻成人网| 伦激情人妻另类人妻| 久久一区二区蜜桃| 精品乱码在线观看| 青青草久久一区网| 一区二区三区精品黑丝白丝酒店对鸡| 嗯啊视频免费在线观看| 精品久| 亚洲 欧美 日本 国内 首页| 久日91在线| 久妇网| www.久久| 99热这里只有精品地址 | 国产又大又粗又色生活片亚洲国产精品成人久久久综合免费 | 日本在线激情一区二区三区| 人妻一二三区| 三级日本一区二区三区| 无码人妻一区二区三区免费九色| av日韩中文字幕| 天堂网 主播 亚洲| 日本黄色裸日本黄色裸体 | 97色亚洲| 91老司机视频| 一本色道人妻久久| 91色欧美| 国产一线二线三线av| 国产又大又粗又长视频| 91n免费处女| 久久九精品| 亚洲国内精品成人不卡| 国产二区三区粉嫩在线| 日本999精品视频| 午夜欧美J进J出白浆流出久久久| 99热色这里只有精品| 色性欧美| 一区黄二区黄| 精品网站9999| 国产SV一线| 物尤视频一区二区| 久久中文色图| 天天享受天天看| 欧美白嫩在线放| 久久香蕉超碰97国产精品| 2000亚洲男人天堂| 精品美女久久一二三| 老女人91| 亚洲丝袜二区在线| 九t超碰| 色汉综合| 国产辣妈在线视频福利| 免费视频在线一区二区不卡| 免费观看成人www精品视频| 日韩一级性爱无码| 一类av片在线看| 激情干在线| 狠狠综合| 日本天堂网| 中文字幕AV片| 四虎免费在线播放| 精品人妻av区天天看片| 成人毛片免费| 被男人添B超爽视频| 日本高清_区二区三区| 国产精品青草综合久久| 玖色AV| 亚洲青色欧美| 亚洲天在线| 日本韩高清无砖码22o| 香蕉黄色一级视频| 美国日韩黄色片| 淮穴色AV| 97er欧美性| 九t超碰| 夜夜操美女| 插欧洲美女欧美精品| 91人妻超碰| 青青草久草AV| 啊啊啊啊啊啊啊啊视频| 亚洲色欲天天天堂色欲网女| 日本日皮视频逼| 黄页大片在线观看| 嫩草黄页| 蜜臀久久99精品久久久久| 人人操人人插人人摸人人干| 色婷婷导航| 亚洲av热热色| 国产精品丝袜在线| A级毛片在线看免费| 亚洲国产欧美中文永久| 日韩av三四区| 免费视频观看60秒| 少妇一级婬片免费放一级a性色.| 99综合视频一体| 北京美女一区二区| 天天肏天天干| 强免费黄色网址| 四虎884a| 超碰91在线| 日韩精品视频在线观看一卡二卡| 91 丝袜在线| 99超碰碰| 日韩亚洲中文字幕在线| 欧美老熟另类| 果冻传媒A片麻豆熟妇人妻| 国产女人和拘做爰视频| 女色视频社区| 欧美综色欧| 综合久久六月久久婷婷| 熟女一区二区| 欧美啪啪色吧在线| 久久久免费一级黄片| 久久做97| 亚洲激情视频| 色婷婷电影| 色亚州人久干视频在线观看免费版| 91色综合| 加勒比大香蕉视频在线| 久久久久婷婷精品av电影| 亚洲天堂久| 国产精品久久久亚洲第一牛牛_在线观看 | 大香蕉久久| 久久色情| avav青青草久久夜| 日韩欧美俄罗斯A片| 热久日综合| 自怕偷自怕亚洲精品| 久久国产精品,久久国产| 亚洲另类春色| 婷婷日韩一区二区三区中文字幕在线| 超碰97极品9| 3p国产欧美99热| 久久精品人妻一区二区三区| 国产精品一区二区三区,亚洲综合 性开放中文AV高清无码免费看 | 欧美一区91大爱| 日韩欧美女求操每天更新| www.色婷婷色综合| 美女十八禁| 色999;丁香五月| 国产精品伦理| 九九热视频在线观看| 本道综合精品| 在线观看AV不卡| 婷婷色综合欧美日韩| 日韩在线女优天天干| 亚洲在线| 色综合加勒比四四季| 欧美A片中文字幕| 夜夜福利| 夜间福利片1000无码| 91人妻久久久久久久久久久久久| 综合操逼| 亚洲天天天| 东京热亚洲一区二区| 啊啊啊无码| 麻豆区99999| 亚洲AV无码翔田千里网站| 校园春色亚洲无码| 国产美女高潮叫床视频| 亚洲丨在线| 女同亚洲欧美一二三区久久电影| 亚洲国产美女久久久久| 美女91在线观看| 乱伦av.com| 人妻第一页| 欧美色图中文字幕| 岛国毛片手机在线观看| 五十路熟女在线不卡观看一区二区| 99啪啪| 日本性感人妻91| 超碰久久网| 欧美男人一区| 国内精品久久人妻性色av| 精吧天堂| 草草影院在线视频| 欧美探花网| 97超级久久| 自拍丝袜美腿人妻| 国产午夜无码片在线观看影视 | 黄色视频特级毛片| 东京热大香蕉| 亚洲色图欧美另类在线| 九久9精品| 亚洲色欲天天天堂色欲网女| 亚洲在线观看| 亚洲情色一区三区| 91精品国产高清久久久久久,亚洲成人 | 88在线一区二区三区| 大香蕉在线视频15| 国模无码一区二区三区在线| 成人怡红院| 97视频在线视频| 伊人综合色网| 日本一本道A级黄色毛片试看60分钟| 1240青青草一区二区三区视频天爱| 欧美日韩一干二干| 久久国产视频性吧 | 久久精品老司| www色色com| 制度丝袜99| 中国人高清www色视频免费| 果冻传媒一区二区三区| 亚洲天堂另类小说男人| 偷窥自拍亚洲天堂网爆| 少妇一区二区三区高速| 好属操| 欧美亚洲韩国视频十五区| 熟女日韩| 亚洲在高跟鞋自慰久久在色线| 国产做?爰片久久毛片?片美国| 欧美性爽xyxOOOO| 欧美人妻一区二区| 一区| 99国产精品人妻人伦| 综合自拍| 国产精品无码久久久久2028| 久久久96| 人妻91少妇| 色婷婷一区二区三区久久午夜 | 久久成年片色大黄全免费网站| 亚洲 欧美 日韩另类 麻豆| 亚洲激情天堂网| 日本裸体久久色噜噜| 九九黄色网| 中文字幕免费看大片| 国产对白刺激视频| 欧美精品二区视频在线| 亚洲成人ab| 色约约一区=区三区| 亚洲色图第一页| 99只有精品| 欧美视频激情久久久久久| 人妻在线臀日韩| 狠狠狠一区二区三区| 囯产精品一区二区三区线|亚洲人成无码网WWW动漫|国产精品免费一级... | 怡红院成人av| 国产精品午夜成人福利| 青青草视频爽一爽| 91亚·色| 丰满人妻一区二区三区免费,| 一块操欧美| a在线观看| 人妻中文在线| 另类在线| 久久性爱视频| 亚洲欧美精品91| 亚洲天堂综合AV| 久久久蜜桃一区二区三区| 偷拍 精品另类 凸凹了四区| 激情五月天婷婷| 97色伦欧美| 91九久| 熟女一区二区| 日本A级视频| 欧美韩国你懂得在线| 亚洲成人妻日韩在线| 狠狠做深爱婷婷久久二区| 中文欧丝袜诱惑| 天天综合网视频91| 少妇的嫩逼图片| 亚洲黑人在线| 国产美女口爆吞精视频| 黑人白女精品一区| 国产 无码 一区二区|