久久亚洲成a人片熟女精品色一区二区三区|国产精品视频第一精品视频|av天堂热无码手机版|亚洲?v无码久久无遮挡|国产精品偷伦视频免费观看国产|麻豆国产自产精品丰满熟妇|av无码av不卡一区二区|久久亚洲精品中文字

ARTICLE DETAIL

資訊詳情

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

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

Rust所有權(quán)與借用檢查:編譯期內(nèi)存管理實(shí)踐 寫 Rust 這幾年被問得最多的一句話就是“所有權(quán)到底是個(gè)啥”。我一直覺得這個(gè)中文譯名有點(diǎn)誤導(dǎo)聽起來像某種法律概念實(shí)際上它描述的是一件特別樸素的事一塊內(nèi)存由誰負(fù)責(zé)釋放、什么時(shí)候釋放、釋放之前誰有資格讀寫。C 里這件事靠人腦記賬Java、Go 里這件事交給運(yùn)行時(shí)在后臺(tái)掃Rust 選了第三條路——把賬本寫進(jìn)類型系統(tǒng)讓編譯器在編譯期替你記。代價(jià)是你得學(xué)會(huì)跟編譯器講道理收益是運(yùn)行時(shí)沒有停頓、沒有懸垂指針、沒有雙重釋放單線程代碼里的迭代器失效問題基本絕跡。這篇筆記把所有權(quán)、借用檢查、生命周期標(biāo)注、智能指針這幾塊串起來講重點(diǎn)放在“它怎么影響內(nèi)存管理”這個(gè)角度而不是復(fù)述語法手冊(cè)。適合已經(jīng)能寫點(diǎn) Rust 但總被借用檢查器攔下來的人也適合從 C 或 Go 轉(zhuǎn)過來、想搞清楚心智模型差異的人。下面所有報(bào)錯(cuò)和改法都是我實(shí)際踩過的代碼可以直接抄去跑。1. 三種內(nèi)存管理路線Rust 為什么挑了最難的這條1.1 手動(dòng)管理與垃圾回收各自的賬單先把三條路擺在桌面上對(duì)比不然后面很多設(shè)計(jì)取舍會(huì)顯得莫名其妙。手動(dòng)管理C、C 的裸指針路線把釋放時(shí)機(jī)完全交給開發(fā)者性能上限最高內(nèi)存布局最可控代價(jià)是任何一次疏忽都會(huì)變成線上事故而且這類事故往往在壓力大的時(shí)候才暴露。垃圾回收J(rèn)ava、Go、C# 的默認(rèn)路線把釋放交給運(yùn)行時(shí)開發(fā)者寫得舒服代價(jià)是內(nèi)存占用曲線偏高延遲不可預(yù)測遇到大堆的時(shí)候一次回收能帶來幾十毫秒的抖動(dòng)。Rust 的所有權(quán)系統(tǒng)是第三條路編譯器在編譯期為每個(gè)值推導(dǎo)出唯一的負(fù)責(zé)方負(fù)責(zé)方離開作用域就自動(dòng)釋放檢查全部發(fā)生在編譯期運(yùn)行時(shí)不需要任何額外指令。路線釋放時(shí)機(jī)運(yùn)行時(shí)開銷典型風(fēng)險(xiǎn)延遲可預(yù)測性手動(dòng)管理開發(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í)開銷”。Rust 的所有權(quán)檢查在編譯完成后就消失了生成的機(jī)器碼里沒有任何一條指令是用來“檢查所有權(quán)”的這叫零成本抽象。你付出的是編譯期的思考成本和偶爾的改寫成本換來的是運(yùn)行時(shí)的確定性。1.2 所有權(quán)本質(zhì)上是一套編譯期推導(dǎo)出來的引用計(jì)數(shù)我習(xí)慣用引用計(jì)數(shù)來類比所有權(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)換人了舊主人再訪問就是越權(quán)。這個(gè)類比還能解釋另一個(gè)現(xiàn)象為什么RcT在 Rust 里被歸到“智能指針”而不是“所有權(quán)”里。因?yàn)橐坏┠阏娴男枰鄠€(gè)所有者編譯期就沒法推導(dǎo)出唯一負(fù)責(zé)方了只能退回到運(yùn)行時(shí)記賬這就是Rc和Arc存在的原因。理解了這個(gè)層次關(guān)系你就不會(huì)覺得RcRefCellT是一堆奇怪符號(hào)的堆砌而會(huì)明白它是“編譯期賬本不夠用時(shí)的降級(jí)方案”。1.3 編譯期到底擋住了哪幾類事故具體一點(diǎn)所有權(quán)加借用檢查主要攔四類問題。第一類是釋放后使用C 里指針指著的內(nèi)存已經(jīng)被free掉讀出來是臟數(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之后原來的迭代器可能指向已釋放的舊緩沖區(qū)Rust 里你在遍歷v的同時(shí)調(diào)v.push()會(huì)直接編譯失敗。第四類是數(shù)據(jù)競爭多個(gè)線程同時(shí)讀寫同一塊內(nèi)存且沒有同步Rust 靠Send和Sync兩個(gè)標(biāo)記 trait 在編譯期就把不安全的共享擋掉。我印象最深的是第三類。早年寫 C 的時(shí)候在一個(gè)循環(huán)里刪元素導(dǎo)致迭代器失效程序在小數(shù)據(jù)量下跑得好好的上線之后數(shù)據(jù)量上來才開始隨機(jī)崩潰查了兩天才定位到。換成 Rust 之后這種寫法連編譯都過不去等于把調(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è)所有者。第三條所有者離開作用域值被丟棄。這三條合起來的效果是任何一塊堆內(nèi)存的釋放點(diǎn)都是唯一且確定的編譯器在生成代碼的時(shí)候就知道該在哪里插入釋放調(diào)用不需要運(yùn)行時(shí)判斷。拿String舉例。let s1 String::from(hello);這一行會(huì)在棧上放一個(gè)三元組指針、容量、長度在堆上放五個(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 走的值。注意這里沒有發(fā)生任何堆內(nèi)存分配或復(fù)制move 對(duì)String這類類型來說是常數(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裝一百萬個(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í)測下來 move 通常是納秒級(jí)clone 一百萬個(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è)類型本身沒有實(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è)常見的性能坑給一個(gè)大結(jié)構(gòu)體derive(Clone)之后在循環(huán)里順手寫.clone()傳參編譯器不會(huì)提醒你代碼跑起來才發(fā)現(xiàn)慢得離譜。我的做法是只有在確實(shí)需要獨(dú)立副本的地方才 deriveClone而且在大結(jié)構(gòu)體上會(huì)刻意不 derive逼著自己去想清楚到底該傳引用還是轉(zhuǎn)移所有權(quán)。順便說一個(gè)實(shí)測有用的小技巧用std::mem::size_of快速看一眼類型的棧上開銷很多“為什么這個(gè)結(jié)構(gòu)體這么大”的疑惑一測就清楚了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ú)說一下。編譯器發(fā)現(xiàn)Box的指針不可能是零于是用空指針這個(gè)非法值來表示None這叫空指針優(yōu)化。這個(gè)優(yōu)化在鏈表、樹這類遞歸結(jié)構(gòu)里非常關(guān)鍵不然每個(gè)節(jié)點(diǎn)都要多帶一個(gè)字節(jié)的判別位再加對(duì)齊填充內(nèi)存占用會(huì)明顯上升。2.4 函數(shù)簽名就是一份所有權(quán)契約我一直建議新手把函數(shù)簽名當(dāng)成一份合同來讀。參數(shù)寫T表示調(diào)用方把這個(gè)值的所有權(quán)交出去了函數(shù)返回之后調(diào)用方不能再碰它寫T表示只借來讀函數(shù)內(nèi)部改不了寫mut T表示借來改借用期間調(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)這四行基本覆蓋了九成場景。我踩過的一個(gè)坑是函數(shù)參數(shù)寫成String但其實(shí)只讀一下長度結(jié)果調(diào)用方每次都得 clone 一份才能傳進(jìn)去。改成str之后String和字符串字面量都能直接傳調(diào)用方省掉了所有 clone。這個(gè)改動(dòng)看起來小在一個(gè)熱路徑上能省掉可觀的分配次數(shù)。3. 借用檢查器到底在檢查什么3.1 共享不可變、獨(dú)占可變借用規(guī)則只有一句話任意時(shí)刻你要么擁有多個(gè)不可變引用要么擁有一個(gè)可變引用兩者不能同時(shí)存在。另外所有引用必須始終有效。這條規(guī)則的動(dòng)機(jī)有兩個(gè)層次。淺層是為了防止數(shù)據(jù)競爭多個(gè)線程同時(shí)讀是安全的只要有寫就必須獨(dú)占。深層是為了防止同一份數(shù)據(jù)在讀取過程中被別處改掉導(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ā)重新分配原來的迭代器變成懸垂指針接著就是未定義行為。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); } }這種“先讀后寫”的拆分模式我用了無數(shù)次幾乎所有的借用沖突都能用這個(gè)思路化解。它看起來多寫了一行實(shí)際上是把原本隱藏的時(shí)序依賴顯式化了代碼反而更清楚。3.2 NLL 讓借用的結(jié)束點(diǎn)變聰明了早期的 Rust 用詞法作用域判斷借用何時(shí)結(jié)束只要變量還在作用域里借用就算沒結(jié)束于是很多寫法通不過。從 2018 edition 開始默認(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之后就沒用了借用提前結(jié)束后面的push就不沖突了。理解這一點(diǎn)很重要它意味著你不需要為了繞開借用檢查而寫一堆莫名其妙的花括號(hào)只要讓借用自然地在最后一次使用處結(jié)束就行。3.3 生命周期標(biāo)注不延長壽命只是描述關(guān)系生命周期這個(gè)詞嚇退過不少人其實(shí)它的作用被嚴(yán)重夸大了。生命周期標(biāo)注不會(huì)讓任何值的存活時(shí)間變長或變短它只是告訴編譯器“這幾個(gè)引用之間的存活關(guān)系是這樣的”方便編譯器做檢查。真正決定值活多久的永遠(yuǎn)是它所在的作用域。最經(jīng)典的例子是返回兩個(gè)字符串切片里較長的那個(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法確定返回的引用到底跟著x還是y活。a的意思是返回值的存活時(shí)間不會(huì)超過x和y中較短的那個(gè)。這是一個(gè)上界約束不是延長。調(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 的有效期不能超過a”。這意味著任何持有Token的地方那個(gè)被引用的字符串也得活著編譯器會(huì)一路向上檢查。這個(gè)傳播有時(shí)候會(huì)很煩一個(gè)底層結(jié)構(gòu)加了生命周期上面三層都得跟著加。我的處理策略是分場景的。如果這段數(shù)據(jù)是短命的、臨時(shí)的、解析完就用完的那就老老實(shí)實(shí)加生命周期零拷貝最快。如果這段數(shù)據(jù)要被存起來、跨函數(shù)傳遞、或者放進(jìn)集合里長期持有那就直接存String用一次分配換掉整條鏈上的生命周期標(biāo)注。這個(gè)取舍在下一節(jié)的實(shí)戰(zhàn)案例里會(huì)詳細(xì)展開。4. 智能指針編譯期賬本不夠用的時(shí)候4.1 Box、Rc、Arc、RefCell 各自解決什么問題所有權(quán)的默認(rèn)模型是單一所有者加獨(dú)占可變這個(gè)模型覆蓋了大部分場景但確實(shí)有幾類需求它表達(dá)不了需要在堆上分配且大小在編譯期未知的遞歸類型、需要多個(gè)所有者共享同一份數(shù)據(jù)、需要在只有不可變引用的前提下修改內(nèi)容。這三種需求分別對(duì)應(yīng)Box、Rc/Arc、Cell/RefCell。類型所有權(quán)模型線程安全運(yùn)行時(shí)開銷典型場景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)容選型的順序我一般是這樣的先問是不是遞歸類型或需要 trait 對(duì)象是就上Box再問是不是真的需要多個(gè)所有者如果只是讀取共享用Arc包只讀數(shù)據(jù)就夠了別急著上RefCell最后才問是不是需要在不可變引用下修改需要才用RefCell。很多人一上來就寫RcRefCellT其實(shí)八成場景用RcT或者干脆傳引用就能解決白白引入了運(yùn)行時(shí)開銷和 panic 風(fēng)險(xiǎn)。4.2 Rc 加 RefCell 的代價(jià)具體在哪RcT的每次clone都要對(duì)引用計(jì)數(shù)做一次加一每次drop做一次減一減到零才釋放。這些操作在單線程里是普通的整數(shù)加減開銷很小但不為零。RefCellT則維護(hù)一個(gè)借用計(jì)數(shù)器borrow()時(shí)檢查當(dāng)前有沒有可變借用有就 panicborrow_mut()時(shí)檢查計(jì)數(shù)器是不是零不是零也 panic。這兩個(gè)檢查都是運(yùn)行時(shí)分支編譯器沒法優(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è)模式在雙向鏈表、樹結(jié)構(gòu)里都會(huì)用到我建議只要結(jié)構(gòu)里出現(xiàn)“指回去”的邊就默認(rèn)用Weak不要等到內(nèi)存漲上去才回頭改。4.3 有時(shí)候該退一步換數(shù)據(jù)結(jié)構(gòu)而不是堆智能指針這是我踩過的最大的一個(gè)坑。早期寫一個(gè)圖結(jié)構(gòu)的處理邏輯習(xí)慣性地用RcRefCellNode表示每個(gè)節(jié)點(diǎn)節(jié)點(diǎn)之間互相引用。代碼能跑但性能很差而且一旦涉及并發(fā)就完全沒法用因?yàn)镽c根本不是Send。后來改成用VecNode存所有節(jié)點(diǎn)節(jié)點(diǎn)之間用usize索引互相引用性能提升非常明顯代碼也短了。struct Graph { nodes: VecNode, } struct Node { edges: Vecusize, // 索引而不是引用 }索引方案的代價(jià)是你得自己保證索引有效刪節(jié)點(diǎn)的時(shí)候要處理懸空索引。但它換來的是連續(xù)的堆布局、零引用計(jì)數(shù)開銷、天然的Send Sync而且序列化也簡單得多。我現(xiàn)在的判斷標(biāo)準(zhǔn)是如果一個(gè)數(shù)據(jù)結(jié)構(gòu)里RcRefCell出現(xiàn)超過兩處就該停下來想想是不是該用索引或者 arena 了。5. 一個(gè)真實(shí)場景的重構(gòu)從編譯不過到跑得穩(wěn)5.1 需求解析文本并緩存字段假設(shè)要寫一個(gè)小模塊從多行文本里解析出鍵值對(duì)緩存起來供后續(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返回的引用直接指向原始輸入零拷貝速度很快。問題出在調(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說不能返回指向局部變量的引用。這不是編譯器的刁難content在函數(shù)結(jié)束時(shí)就 drop 了返回的Config里那些指針會(huì)立刻變成懸垂指針。如果這段代碼在 C 里寫編譯能過運(yùn)行時(shí)讀到的就是垃圾數(shù)據(jù)而且可能好幾個(gè)月都不出問題直到某次內(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ì)于配置文件這種一次性加載、長期駐留的場景這個(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)庫提供的枚舉只有Borrowed和Owned兩個(gè)變體。它的好處是調(diào)用方不用關(guān)心底層到底是借用還是擁有用.as_ref()或Deref就能當(dāng)str用。壞處是它仍然帶著生命周期參數(shù)跨函數(shù)邊界的時(shí)候該傳播還得傳播而且枚舉本身占的??臻g比單純的str大具體多大可以用size_of實(shí)測一下不同版本和優(yōu)化下會(huì)有差異。我現(xiàn)在的選擇順序是數(shù)據(jù)生命周期短、調(diào)用鏈淺用str加生命周期數(shù)據(jù)要被長期持有、跨線程傳遞用String兩者之間搖擺不定的中型場景用Cow。這個(gè)順序不是教條但你照著走能少走彎路。6. 高頻報(bào)錯(cuò)與排查速查6.1 錯(cuò)誤碼對(duì)照表被借用檢查器攔住的時(shí)候先看錯(cuò)誤碼再看提示里的“誰的借用還沒結(jié)束”。下面這張表是我整理的高頻錯(cuò)誤基本上覆蓋了日常八成的情況。錯(cuò)誤碼含義典型改法E0382使用了已經(jīng) move 的值改傳引用或在轉(zhuǎn)移前 cloneE0499同一作用域內(nèi)兩次可變借用拆分成兩個(gè)階段或用索引代替引用E0502可變借用與不可變借用沖突先讀后寫或縮短不可變借用的生命周期E0505借用還沒結(jié)束就要 move讓借用先結(jié)束再 moveE0515返回了局部變量的引用返回?fù)碛兴袡?quán)的類型E0597被借用的值活不到那么久調(diào)整作用域順序或改為擁有E0716臨時(shí)值在借用期間被釋放先用 let 綁定成變量再借用E0106缺少生命周期標(biāo)注按省略規(guī)則補(bǔ)上或改成擁有類型E0716 值得單獨(dú)提一句很多人寫過類似的代碼然后一臉茫然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()借出來的引用立刻懸垂。先綁定到tmp之后tmp活到作用域結(jié)束借用才合法。這類問題的排查思路很統(tǒng)一看那個(gè)被借用的值是不是臨時(shí)值是就給它一個(gè)名字。6.2 排查順序先找誰借了誰再看誰要活多久我處理借用錯(cuò)誤的固定流程是這樣的。第一步看錯(cuò)誤提示里點(diǎn)名的變量確認(rèn)是“值被 move 了”還是“借用沖突”。第二步如果是借用沖突從報(bào)錯(cuò)位置往上找找最后一個(gè)使用這個(gè)引用的地方那里就是借用結(jié)束的位置。第三步如果想讓借用提前結(jié)束就把后面的寫操作挪到那之后或者把讀的結(jié)果先取出來存成獨(dú)立的值。第四步如果怎么調(diào)都不行說明數(shù)據(jù)結(jié)構(gòu)的所有權(quán)模型設(shè)計(jì)有問題考慮換成索引、Rc或者擁有類型。這個(gè)流程里第三步最常用。舉一個(gè)我經(jī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)場結(jié)束后面的插入就自由了。這個(gè)技巧在處理哈希表、緩存的時(shí)候特別好用我基本養(yǎng)成了習(xí)慣只要借出來的值很小且 Copy先拷貝再用。6.3 幾條踩出來的實(shí)操心得第一別怕加花括號(hào)。雖然 NLL 已經(jīng)聰明很多但在某些復(fù)雜表達(dá)式里顯式劃一個(gè)作用域讓借用提前結(jié)束比絞盡腦汁調(diào)整順序省事得多。第二clone()不是洪水猛獸在冷路徑上用 clone 換代碼清晰度是完全劃算的我反對(duì)的是在熱循環(huán)里無意識(shí)地 clone。第三遇到RcRefCellT的borrow_mutpanic先找有沒有在同一段代碼里同時(shí)持有兩個(gè)借用尤其是鏈?zhǔn)秸{(diào)用里臨時(shí)值還沒釋放的情況把中間結(jié)果用let綁定出來往往就好了。第四函數(shù)簽名優(yōu)先用借用只有在確實(shí)需要保存或跨線程的時(shí)候才用擁有類型這條規(guī)則能讓你的模塊接口干凈很多。第五如果一段邏輯里到處都是unsafe或者反射式的類型轉(zhuǎn)換那多半不是所有權(quán)的問題是數(shù)據(jù)結(jié)構(gòu)選錯(cuò)了回頭看看第 4.3 節(jié)。關(guān)于內(nèi)存管理我個(gè)人在實(shí)際操作中最深的一點(diǎn)體會(huì)是所有權(quán)系統(tǒng)真正改變的不是你寫代碼的語法而是你設(shè)計(jì)數(shù)據(jù)結(jié)構(gòu)的方式。寫 C 的時(shí)候我會(huì)自然地想“這塊內(nèi)存誰 free”寫 Java 的時(shí)候基本不想寫 Rust 之后我會(huì)在動(dòng)手寫第一行之前就想清楚“這個(gè)值的生命周期有多長、誰能改它、要不要共享”。這個(gè)思考前置的過程一開始很別扭習(xí)慣之后反而省掉了大量調(diào)試時(shí)間因?yàn)楹芏鄦栴}在敲代碼的時(shí)候就已經(jīng)被逼著想明白了。
返回列表
PREV
查看更多資訊
NEXT
返回資訊列表
欧美躁死她一区二区| 五月婷婷六月丁香| 日韩欧美麻豆| 国产精品呦一区二区三区| 色爱三区| 蜜乳中文字幕a在线| 久久精品电影| 久久人妻四季| 草草影院最新网址| 国内精品嫩模A∨私拍小视频| 欧美高潮| 日韩成年人性爱视频| oumeisetu综合| 综合影视国产无码| 亚洲图片激情综合另类| 天美国产三级传媒| 国产精品亚洲一级av第二区| 色综合av男人天堂| 目产99999久久999| 成人在线视频网| 天天操天天射青青草| 国产路线专区| 九九九不卡| 亚洲欲| 亚洲激情视频| 在线 亚洲 网爆 自拍| 久久久无码av精| 亚洲操操操无码| 内射卯月麻衣| 大但人体久久久久| 少妇久久久久久| 日本阿v天堂在线观看| 国产福利影视| 在线日韩视频| 国产天美欧美| 亚洲欧美日韩综合在线尤物 | 久久精品亚洲婷婷| 国产亚洲日本精品在线| 色呦呦呦在线观看视频| 九九这里只有精品| 日日骚 av| 精品久久久久久中文字幕视频免费| 无码免费在线观看黄色片| 日本韩欧美在线播放a| 91大神电影天堂| 久久久熟妇熟女国产| 欧美第二页午夜| 日韩成人高清一区二区| 91天美传媒在线观看| 色综合久久88色综合久久天天| 精品久久久无码| 在线一区| 天天综合网日韩7799| 精品久久久不卡一区二区| 亚洲性爱电影| 中文一区二区| 色99色| 男人的天堂 在线一区| 中文字幕视频一区视频二区| 国产AV线| WWW啪啪的com| 亚洲视频,小说| 金莲网址| 欧美91久久久久| 中文字幕成人| 蜜乳av一区二区| 亚洲成人AB| 色婷婷五月天| 欧美国产欧美在线观看| 亚洲啪啪视频免费| 91在线无码精品秘 软件| 青娱乐日韩无码| 福利天堂| 玖玖爱免费观看视频| 久久久久久久78| 亚洲精品97| 艳美熟妇先锋一二三区| 最新的亚洲无吗| 伦理弟一页| 女人爽到高潮潮喷18禁网站| 国产美女自拍AV| 91超碰人人| 亚洲AV秘 精品久久老牛影视| 日韩精品人妻中文字幕不卡乱码| 91殴美大片| 国产91亚洲精品一区二区三区| 岛国精品视频在线观看| 特色a在线上| 最新加勒比丝袜在线| 一起草欧美| 女同性恋一区二区三区精品视频| 亚洲美女AV无码| 97就爱干| 久久伊人青青草| av中文在线| 国产日逼视频| 黄色人人| 久久久久久久久女黄| 国产久久视频| 日本三级A片网站com| 欧美天天搞| 人妻密肉在线观看| 亚洲天堂色图| 三级AV入口| 99久久国产精品免费高潮| 国产又大又粗又长视频| 四色永久成人网站| 精品久久无码午夜福利| 爱妃国产亚洲视频中文字幕| 欧美在线 亚洲| 亚洲色图加勒比| 色99在线| 狠狠色噜噜狠狠狠狠狠色综合久久 | 91久久久视| 日韩成人性日韩成人性爱视频在线免费观看| 97电影院超碰| 国内自拍 日韩激情 99| 免费超碰97在线观看| 东北少妇高潮zzzz| 久热在线精品免费观看| 浓厚中出中文字幕在线| 91操操操操| 亚洲欧美爆| 综合国产97| 91 亚洲 欧洲| 久热色情精品| 91久久精品中文字幕| 91麻豆天美传媒HD| 三级网站超变态精品| 熟女一区二区| 久久国产999| 亚洲成人免费电影| 夜夜草我| 温婉少妇玩3p| AV电影在线播放| 亚洲精品久久久久毛片A片拉屎 | 东京热男人的天堂| 久操影视| 国产精品久久久久久久久久二区三区| 色婷婷99| 亚洲国产精品99久久久| 好爽免费视频| 亚洲91网站| 欧美自拍偷拍免费观看| 亚洲AV性爱电影| 国产精品网址| 久久性爱视频免费看| 97超碰精品成| 日韩人妻操B| 凹凸视频特色日本特黄| 天天操人人操狠狠插| 岛国黄| 中文字幕av亚洲在线| 日本乱人伦片中文三区| 国产51色综合久久免费| 在线99热| 欧美综合区| 日韩操逼性鲍| 蜜乳av一区二区| 91精品人妻一品二品三品| 成·人免费午夜在线观看| 亚洲欧洲中文日韩女优乱码| 日本亚洲熟女视频| 日韩99神马视频片| 搡老女人老91二区| 7777欧美成是人在线观看| 日韩在线国产字幕| 日本天堂在线播放| 日本中文字幕在线电影| 六月激情婷婷| 97久久超碰国产网站| 视频二区熟女人妻| 国产欧洲精品亚洲午夜拍精品| 国产91 丝袜在线播放| 免费伦费视频在线观看| 狠狠激情综合狠狠操中文字幕| 人人插人人摸人人| 蜜臀亚洲中文| 四虎av在线| 亚洲高清无毛一区二区| 丁香五月天视频| 久久久亚洲精品电影免费看| 久久不卡一区二区| 少妇专区一二三四五| 九九拍拍精品视频在线播放 | 天天综合,91综合永久| 色婷婷五月综合激情中文字幕| 国产天美欧美| 99国产天美| 2017大香蕉国产精品久久| 夜夜嗨绯色| 97超碰精品成| 欧洲一区二区三区四区在线观看| 少妇的嫩逼图片| 97AV在线观看| 嫩草美女久久| 五月激情啪啪| 东京太热久久久| 99少妇| 91性感在线| 999亚洲国产视频| 乱理日韩中文| 三上悠亚在线毛片91| 国产亚洲精品美女久久久| 中文字幕精品资源在线| 欧美熟妇视频| 丝袜亚洲综合| 无码二级三级| 国产激情久久久| 9999亚洲电影| 亚州黄站| 狠狠干综合| 天天综合网久久ww| 久久国产精品视频| 色综合五月天| 绑缚麻绳人妻寝取完整版| 亚洲色系另类精品国产| 日本精品五区| 欧美日韩m| 日韩无限资源| 国产精品无套内谢| 人人妻人人操人人乐| 夜夜嗷嗷一区二区| 97在线免费| 欧美色www亚洲国产阿娇要播| 久久久婷婷| 午夜精品久久久久久久99热影院| 蜜臀一区二区三区亚洲最新章节在线观看 - 高清蜜臀一区二区三区亚洲全集播放 | 久久直播国产| 开心五月婷婷| 欧美色图人妻| 六月丁香婷| 欧美写真视频一区| 国产h片在线观看视频| 亚洲天堂日本| 日韩亚洲中文字幕在线| 中文字幕精品一区二区精| 夜夜夜久久| 欧美成人免费在线观看| 久久99草| 999在线电影香蕉| 高清孕妇孕交| 韩国一级做A片免费的| 国产精品久久久啊| 国产内射爽爽大片| 人澡逼| 婷婷久久五月| 国产粉嫩蜜臀av一区二区三区| 欧美专区第一页| 四虎永久在线精品免费网址 | 欧洲中文字幕| 自拍大香蕉乱插| 超碰导航97| 美女诱惑1区2区| 夜夜春夜夜操| 日韩AV色图| 精品毛片av一区二区| 六月丁丁香| 亚洲国产一级黄色视频| 91国产丝袜美女| 五月丁香六月激情| 花花AV导航| 久/久精品99看9| 丁香婷婷五月| 丝袜狠狠草尤物人妻av91| 国产一级内射无挡观看| 色香AV| 天天激色| 亚欧国产无码精品在线| 中文字幕五月婷婷免费| 五月天久久婷婷亚洲| 国产一级作爱毛片| 大香蕉乱级| 9I1性色影院| 久久香蕉超碰97国产精品| 在线一道啪| 亚州日韩97| 一区二区三区成人高清视频| 亚洲国产欧美日韩精品一区二区三区,国产一区二区三区在线看片,欧美性猛交 XXX | 青青草五月天| 精品在线蜜臀| 玖玖综合色| 色情乱伦AV| 欧美18老人禁| 亭亭丁香激情| 黄色AV影视| 国内毛片国产欧美拍| ai欧美亚洲小说| 日夜啪电影| 欧美日韩性爱视屏免费看了| 6080YYY午夜理论片在线观看| 亚洲欧美另类少妇精品| 少妇毛片久久| 激情综合二| 黄色人人| 少妇一区二区三区高速| a片自拍直播视频| 自拍盗摄一区| 精品-91人妻子系列| 午夜爽爽爽| 九热大香蕉| www.夜夜操| 91精品国产高清久久久久久,亚洲成人| 日韩激情无码影院| 日韩乱伦AⅤ| 国产亚卅97| xxx亚洲午夜天堂| 亚欧精品久久久久久久久久久| 欧美大香蕉同搞| 5252色欧美在线男人的天堂| 色爱欲亚洲| 国产性感骚丝袜在线| 欧美大波激情xxxx| 亚洲精品国产拍免费91在线| 拍拍拍拍大尺度黄色三级片拍拍拍拍拍照| 亚洲欧美激情另类色图| 国产精品亚洲天堂网址| 加勒比无码毛片| 超碰综合97在线| 激情婷婷丁香| 就去色综合| 欧美熟女丝袜| 国产精品国产自产拍高清AV| 欧中日成人免费影视| 久久久久人妻二区精品叶可怜| 91福利网在线观看| 1769一区| 99re免费视频精品全部| 26uuu性| 夜夜嗨一区二区三区直播内容| 蜜臀99999| 在线观看一卡二卡| 中文字幕少妇色| 刺激精品视频| 啊好大好舒服| 麻豆2区1区天美| 国产人伦精品一区二区三区 | 国产自制av蜜乳| 视频一区二区免费在线| 免费观看国产小粉嫩喷水精品午| 人妻在线视频| 操逼日批| hd成人一区二区在线| 欧美在线干| 一本一道vs波多野结衣| 中文字幕在线日亚州9| 亚洲AV噜噜狠狠网址蜜桃动漫| 亚洲情色中文字幕一区| 免费久久一级毛片大黄| 二色av| 亚洲五月天激情| 德国一二三不卡| 日本性爱少妇| 国产女生在线| 欧美色图亚洲色图成人在在线| 欧美激情一区二区| 91丨国产丨白浆| 啪啪91| 欧美性暴力猛交XXXX| 99re视频在线观看这里只有精品| 自拍视频大全亚洲专媒视频/一区二区三区| 五月丁香激情啪啪| 久久久草成人网站久久久草成人久久久草久久久 | 亚洲成人性爱在线观看| 日本韩国一本产品小视频日本韩国一本产品久久久产品小视频日本韩国一本产品久 | 久久9精品网站| 本道综合精品| 成人av性爱电影在线观看| 国产毛片片精品天天看视频| 我要看免费韩日黄片| 自拍大香蕉乱插| 小草精彩毛片| 97视频播放| 日韩91网站| 天堂无码精品国产久| 嗯啊抽插大香蕉网页| 殴美牲| 婷婷久久久精品| 91老司机精品| 日本国产欧美高清在线| 亚洲网自拍| 欧美综合网1| 国产精品美女视频诱惑| 五月丁香久久| www色色com| 婷婷五月天色色| 人人澡综合涩| 91亚洲综合| 人人操人人插人人摸人人干| 去干网最新版| 后入式五六区| 中文字幕乱在线伦视频中文字幕乱码在线 | 久久婷婷热| 亚洲综合成人网| 婷婷香蕉欧美在线一区二区三区 | 加勒比在线观看一区二区| 99久视频| 丝袜熟女一区二区三区| 江都AV在线| 中文字幕欧美精品亚洲日韩蜜臀| 综合久久欧美| 日夜尻逼网| 熟妇人妻丰满久久久久久久无码| 天天综合欧美| 91天堂色男人的天堂| 狠狠躁天天躁日日躁| 毛片麻豆91糖心精品毛情片| 天天综合~91| 99热免费| 久久精品国内Av熟女高清| 天天做日日爱夜夜爽| 亚码人妻| 国产小黄片在线免费观看| 69超碰综合| 少妇色综合| 99草精| 大JI巴好深好爽又大又粗视频| 丁香五月天啪啪| 日韩欧美中文字幕搭讪巨乳美人妻视频| 国模无码一区二区三区在线| 精品人妻视频一区二区在线播放| 亚洲中文字幕熟女| 大香网伊人久久综合网eew| 精品日韩中文在线| 天天综合网站| 日日97| 日韩激情小说一区二区| 少妇免费视频| 欧美色图亚洲色| 91丝袜美腿网站| 亚洲 欧美 日韩 国产一区二区 | 噜噜噜无码AV一级一级久久影院| 久伊人网78| 男人的天堂不卡一区二区| 欧美亚洲小说| www.久久99| 九九九九九九九九九九九蜜桃| 国内精品嫩模A∨私拍小视频| 60秒试看最爽10分钟网站| 亚洲国产97| 一区| 天天天天干| 色综合一本| 精品乱码在线观看| 探花一区二区三| 玖玖综合色| 国岛片视频| 天天激色| 亚洲影视综合网| 1769国内精品视频| 蜜臀99久久精品久久久久久| 欧美中文字幕男人天堂久久精品 | 好爽免费视频| 长长久久免费视频| 激情欧美97| 综合天天网| 九九碰九九爱97超碰| 欧美自拍网| 麻豆天美传媒在线视频天堂| 日韩一级欧美一级国产一级台湾| 国产日本熟女顶级一区二区三区视频 | 亚洲97成人在线观看| 日韩欧美偷拍美女视频| 韩日性爱av| 后入式视频国产自| 97国产精品国| 中文字幕精品一区二区精| 人妻人人澡人人爽人人| 美女诱惑1区2区| 久久九九国产精品| 免费人成在线观看网站品爱网| 青青草中日韩在线| 91欧美高清| 欧美精品庄| 男人精品天堂一区| 四季AV综合网址| 巨爆乳一区二区爆乳区| 97伊人网| 欧美成人精品一区二区三区| 自拍内地三级在线观看| 日韩图色| 日本三级日本三级三级人妇四虎| 99久久精品无码一区二区毛片免费| 天天摸,夜夜摸| 国产一级高清免费观看| 日本大香蕉综合网| 日本A级视频| 欧美日韩国产中文精品字幕自在自线| 绯色一区二区三区不卡少妇| 亚洲男人天堂视频| 男人精品天堂一区| 60秒免费视频| 亚洲熟久久| 日韩欧美中文日韩欧美色| 丝袜色综合| 日日妻色网| 美女国产一区二区久久| 美國A片| 91啪啪| 亚洲Av噜噜一区二区三区妖精| 亚欧Av| 精品欧美老熟女一二区| 日日骚中文字幕| 传媒免费一区二区三区| 精品国产99| 天天天乱色综合全| 99热在线观看| 国内亚洲精彩视频在线| 69视频入口| 欧美不卡五十路| 国产2.3.4区| 亚洲精品九九九九九九| 男人天堂综合| 7月婷婷综合| 婷婷综合久久| 国产人妻精品久久久一区二区三区| 国产一在线观看| 狠日欧美| 啊啊啊慢点| 91精品人妻一品二品三品| 玖玖爱综合| 欧美亚洲日韩16色| 伊人嫩草| 综合激情一一91| 天天影视之亚洲综合网| 超碰97久| 天天综合麻豆视频| 三四中文字幕| 精品国模无码| jazzjazz国产精品麻豆| 九九AV| 四虎av在线| 亚洲综合九九| 亚洲风情在线观看| 国产精品久久久久9999小说| 欧美第一页| 密乳无码| 91人妻尻屄视频| 少妇99成人麻豆| 亚洲天堂男人在线| julia高潮后不停追击中出| 99re3这里只有精品| 久悠悠av| 亚洲影院小综合| 99999这里都精品| 78m啪啪啪| 亚洲天堂五月天国产| 1禁看欧美黄片免费看| 五月天综合| 欧美成人综合| 天美传媒婬乱在| 亚洲动态色图| 日本精品第一视频在'| 啊啊啊啊二区好大| 久久午夜神马| 久久免费少妇| 久久一区二区三区入口| 日韩天堂av电影在线观看| 色悠久久久av| 乱伦一二三区| 另类图片五月| 超碰97.com| 大香蕉淫人| 亚洲国产精品无码AV在线| 成人资源中文字幕在线观看天天| 最新加勒比丝袜在线| 国产原创精品| 天天干夜夜鈤| 国产精品熟女丝袜一区二区| 九九九九久久久| 青青草丝袜在线视频| 999国产精品999| 很很很很操| 秋霞操逼片| 亚洲另类综合欧美| 人妻内射一区二区在线视频| 玖玖资源视频一区二区三区| 色九久| 大二网站亚洲| 强奸国产在线| 思思热在线观看| 亚洲人精品久久久| 亚洲午夜福利视频| 任你干在线视频| 伊香蕉综合久久久久久久噜噜噜| 99久在线精品99re8| 神马视频久久久久久| 欧亚成人在线视频| 欧美亚洲系列| 极品综合| 另类视频在线| 国产精品suv一区| 亚州黄站| 大香蕉视频一二三区| 中国亚洲呦女专区| 一区二区三区男女操逼黄色小电影| 欧美97日韩精品| 超碰碰97资源站| 操逼国产免费| 亚洲天堂人妻一区二区| 国产精品香蕉| 色婷网| 凹凸 69堂 在线播放| 激情视屏国产乱伦强奸| 91亚洲精品青草| 日韩啪啪啪视频| 精品人妻一区二区三区四区不卡在| 久久9视频| 啊啊啊快操我视频| 91亚洲色图| 97干色天堂| 国产区在线| 日韩另类色图| 日本孕妇一区二区视频操逼免费看 | 制服少妇欧美| 久久久精品| 久久女婷| 久久99草| 黄色AAAAA欧美| 超碰天天操| 亚洲97成人在线观看| 亚洲91少妇| 97ai亚洲| 国产 丝袜 欧美中文 另类| 蜜臀va69| 亚洲性爱高潮影院| 日小BB小视频| 亚洲精品欧洲精品| 亚洲国产欧美一区二区潘金莲| 天天日天天操VV| 色综合国产在线观看| 久久亚洲影院一区二区| 久久在肏| 神马久久久久久久久久| 大香蕉一级黄色片久久| 艹我哪美一区无码| 91精品人妻一区二区三区蜜桃| 日韩不卡av一二三| 日韩欧美久久婷婷网站| 久久啊哟| 国产精品直播在线观看直播| 欧洲天天在线| 另类图片天天影视| 亚洲人精品久久久喷水| 性久久| 欧美性性性| 日本免费人成视频播放120秒| 欧美黑人极品高潮喷吹熟女黑人性暴力日韩在线欧美极品一区二区老师 | 亚洲少妇自拍中文字幕懂色| 麻豆亚洲Av成人无码一区精品| 香蕉99秘 一区精品蜜桃臀| 天天综合有色网| 天天夜躁日日躁狠狠2002| 中文字幕欧美日本乱码一线二线| 日韩成人大片一区二区| 麻豆色99999| 色色五月丁香| 欧美中文综合| 亚洲成人一二三区| 99色热| 搡老女人老91妇女老熟女| 亚洲情色电影网| 亚欧无码在线| 91综合色噜噜| 久久精品电影在线| 欧美九九爱| www.91久久| 大香蕉草草| xxx0国产在线播放| 国产一区二区精品久久99| 精品夜夜澡人妻无码AV| 豆1无夜无码| 国产少妇肉丝在线观看| 久久精品一区二区一8| 精品中文日韩字幕视频| 久视频在线观看| 中文字幕91综合| 丁香六月啪| 操b在线观看| 欧美在线中M| 欧美白嫩女HD| 国产a级精品| 国产日韩欧美亚洲精品95| 91美女视频直播| 风骚少妇视频中文字幕| 天天综合精品| 福利社区午夜一区二区| 青青久草| 青青草手机在线免费观看| 日本丝袜人妻内射| 1769国内精品视频| 有码专区最新中文字幕有码| 欧美亚洲高清晰| 成人影 天天操 亚洲| 国产精品久久久久亚洲av| 欧洲综合色| 另类 综合 日韩 欧美 亚洲| 真实高潮91| 精品久久久中文字幕不| 丝袜狠狠草尤物人妻av91| aaaa少妇高潮大片| 凸凹视频在线观看| 成人片在线播放| 国产精品 久久久精品一牛| 十八禁视频一区二区| 91性高朝久久久久久久久| 67914在线兔费成人视频| 蜜桃网熟妇| 亚洲自拍另类丝袜综合| 五月婷婷大香蕉| 日韩在线76| 欧美日韩国内不卡| 福利社区午夜一区二区| 精品对白久久不卡| 污色区网站| 樱花蜜乳av| 91强热人妻| 国产美女mm131爽爽爽爽| 精品三级在线专区| 伊人91| 伊人嫩草| 91AV天堂| www.人人摸在线视频| 老熟女91视频| 亚洲影院365| 日韩操逼HD| .精品人妻一区二区三| 99999re| 韩美日操逼| 啊啊啊好多水| 欧美激情另类一区二区| 欧美日韩性爱视屏免费看了| 免费一级特黄特色大片在线观看看 | 欧美特大AA级黄片| 亚洲欧美日韩偷拍色图| 欧美性夜| 国产精品免费1区2区视频| 国产欧美精选激情视频| 欧美成人性爱视频大全| 精品国产嫩穴视频| 色综合久久夜色精品国产天堂| 丝袜无码a片| 日韩pv中文| 欧美专利1区2区3区4区5区免费| 中文字幕在线观看AV| 久久视频少妇美女| 欧美人妻另类在线| 亚洲天堂电影网99999| V A在线| 一起草三级AV电影在线观看| 亚洲欧美首页| 可能人人看人人摸| 中日韩久久久| 嗯嗯嗯啊啊啊在线免费观看| 欧美色偷拍| 69综合网| 亚洲少妇在线影音| 久久一本大香蕉 | 少妇综合| 女人与公拘交酡2020视频| 强奸a片网| 亚洲色综合| 久神马| 一区二区三区四区五区久久久久久| 中文字幕、久久精品国产2020、久久综合久久自在自线精品自、亚洲 | 人妻色情天天操| 91视频伊人| 亚洲第2页| 人妻插插人妻人| 国产天美传媒精品| 噜噜瑟| 99re在线| 黄片免费视频2019| 大香蕉久| 丁香五月综合| 精品二区三四区五电影 | 91色夜| 亚洲中文字母在线播放| 麻豆AV96熟妇人妻| 欧美性天天影院| 天天操天天舔| 日本操逼aaaaa| 96精品在线| 欧美成97爱| 日韩在线欧美精品一区二区| 亚洲一区二区麻豆影院| 亚洲色图8| 亚洲 欧美 精品专区 极品| 婷婷激情五月| 亚洲吊色| 久久五月天婷婷丁香中文字幕| 91精品女厕偷拍视频| 另类图片五月| 91 丝袜在线播放| 人妻久久久久久久久久久久久久久| 啊啊啊啊,啊啊好多水| 日本精品无码三级网站| 一本大道综合伊人精品热热| 国产在线综合网| 色婷婷蜜臀av| 奇米四色网| 99热官网| 久久6热精品99视频| 成人乱人伦一区二区| 91丨九色丨43老版熟女| 亚洲淫乱骚妇AV| 久热在线精品免费观看| 91成人国产综合久久精品蜜月| 天天欲望网| 亚洲少妇喷视频看| 国产精品久久| 久久伊人大香蕉| 亚洲综合夜色| 91AV入口| 国产最新AV| 精品久操| 久操网视频| 免费看国产大AB| 亚洲国产成人高清在线| 九九热av| 午夜高清成人在线视频| 九九热这里只有在线精品视 伊人草 成人菠萝蜜视频在线观看 | 日韩成人人妻网站| 日本日皮视频逼| 91日产欧美| 日本在线激情一区二区三区 | 久久久久网站-538在线视频-欧美永久乱码 | 国产主播福利| 91neishe| 久久二| 乱理日韩中文| 性色生活片久久毛片婬片免费放女人一级毛片 | 诱惑网综合| 思思性爱| 亚洲成人贴图| aaa淫乱视频| 亚洲欧洲av影音| 六月婷激情福利天堂69| 久久精品国产亚洲妲己影视| 啊啊啊啊啊好舒服视频| 黑丝内射一区二区三区| 女生看匆91网站| 99久视频| 精品十八在线观看| 操操啪| 久久久久久九九九九九九| 久久五月份| 色黄色美女大长腿午夜视频| 97伊人超碰| 日韩国产十八禁| 麻豆这里只有精品| 99re99在线视频| JULIA一区二区三区在线播放| 久久妇| 99久久精品无码一区二区| 99re视频在线播放青草| 无码自拍SM| 99999久久精| 一区,二区,三区视频| 丁香五月激情五月| 国产亚洲精品农村妇女| 亚洲国产精品无石码久久| 狠狠2050在线观看| 久久99午夜精品一区人妻| 日韩综合无码一区久久92| 老熟女熟妇| 天美麻花大全视频| 日韩无码极品| 国产精品一二三| 夜夜国产一区| 天美AV片| 久久久久9| 国产日产精品久久快鸭的功能介绍| 亚洲三级。日韩三级| 91在线|亚| 久久露脸国产老熟女| 人妻天堂网| 国内外毛片在线观看| 久久鲁夜| 另类一区| 天天激情综合站| 日本阿v天堂在线观看| 色香网| 91国产在线精品| 人人射人人操人人摸| 91大神精品长腿在线观看网站| 亚洲吊色| 极品尤物在线观看| 夜夜影视四色| 日韩无码a片| 日本人妻天堂网站在线播放| 国产中文精品一区二区在线观看| 探花视频免费观看国产专区| 亚洲青青草| 精品熟女一区=区三区| av网站在线观看了| 久久午夜神马| 人妻天天爽夜夜爽爽| 国产精品人妻免费精品| 国产精品另类一区大香蕉| 国产热av| 玖玖爱伊人玖玖爱| 内射黑丝袜| 99国产精品人妻人伦| 婷婷六月天| 丰满欧美少妇| 天天综合AV| 亚洲精品久久久久久久久豆丁网| 精品少妇人妻av久久免费| 欧美激情内射| 青青伊人久久| 2019午夜福利视频| 强奸少妇AV导航网| 国产日本久久免费精品| 国内精品嫩模A∨私拍小视频| 99精品丰满人妻无码| 性色乱AV一区二区| 不卡啪啪视频| 少妇xx精品| 极品尤物自安慰| 国产激情av女片自拍| 岛国精品视频在线观看| 五月丁香综合啪啪| 99精品在线观看| 国产亚洲禁久一区二区| 2020国产精品| 欧美性爱18观看| 美女黄色91| 精品无人区麻豆乱码久久久| 欧美躁死她一区二区| 欧美性天天影视| 野狼激情网| 国产青一二三| 亚洲有码 欧美精品| 欧美性生活综合| 夜夜爽爽爽| 国产传媒一区日韩| 韩日男人的天堂| 91蜜臀熟女| 综合网久久| 人人摸人人舔一区二区| 久久在肏| 天堂69亚洲精品中文字| 欧美色图91| 欧美一区二区三区互相| av网站在线看| 亚洲综合另类| 天天澡天天爽日日AV| 啪啪视频亚洲第一| 99操逼| 中文字幕亚洲欧美在线不卡| 天美传媒av在线| 亚洲欧美爆| 免费草草草草草视频| 中文字幕、久久精品国产2020、久久综合久久自在自线精品自、亚洲 | 久久免费中文字幕在线观看| 亚洲色五月| 91成人国产综合久久精品蜜月| 天天性射网| 欧美 精品国产制服第一页 | 麻豆精品.欧美精品.日韩精品.| av三级电影在线播放| 无码逼| 精品在线观看视频在线| 欧美毛片在线网| 日韩欧亚中文在线| 天天92av| 三级日本一区二区三区| 成人性爱高清视频免费看| 操比国产| 亚洲av热热色| 国产欧美另类久久久精品课程| 亚洲无线码欧洲精品区别| 五月天婷婷综合| AV天堂丝袜| 美女t无毒不卡不卡| 亚洲人妻中文在线视频| 精品丰满人妻一区二区三区免费观| 久久久久13| 动漫片子网站3黄| 日本三级精品| 极品美女福利在线观看| 久久超碰亚洲人| 中文久久96| 午夜噜噜噜| 全免费a敌肛交毛片免费| 激情五月天婷婷| 99999精品成人| 天堂男人网| 综合五月婷婷亚洲一区| 97国产精品国| 少妇第一页| 在线二区不卡| 牛牛AV人人夜夜澡人人爽| 91九色精品熟女内射| 伊人午夜福利视频| 欧美日韩日产免费网站看| 热天堂一区二区| 97综合国产| 九九热在线精品视频| 久久华人网| 国产精品制服丝袜清纯唯美 | 特级毛片特黄久久免费看| 国产夜夜艹| 97免费在线| 一区二区影院| 日韩在线97| 国产AV人人夜夜澡人人爽麻豆| 狠狠爱夜夜干| 中文字幕乱码在线| 操屄日韩| 老熟妇一区二区三区…| 亚州色图第三区| 亚洲欧洲第二视频在线观看色图| 九九超碰综合网| 我要色综合网| 久久精品小视频| 人妻少妇精品视频一区二区三区| 人妻丰满熟妇一区二区三| 中文字幕加勒比海高清无码免费视频| 亚洲av性爱电影| 淫色网综合| 乱伦熟妇一区二区| 91色噜噜狠狠| 激情抓乳插进去啪啪啪日韩| 夜夜操夜夜爽夜夜高潮| 亚欧美无遮挡| 国内偷自视频区视频综合| 十八禁黄色成人网站观看| 激情小说图片亚洲首页| 九九99久久| 99热18这里只有精品| 日韩性爱小视频| 日本中文字幕高跟| 91殴美| 国产亚洲禁久一区二区| 一二三卡欧美日韩人妻免费精品| 国产色呦呦| 欧美中文字幕一区 | 中文字幕一二三| 国产精品爱欲| 国产麻豆一区二三区| 欧美丰满熟妇XXXX性ppX人交| 一区二区视频在看| 免费αⅴ在线观看| 小骚逼被操的爽不爽| 亚洲成人精品在线一区| 操人妻丝袜高跟| 婷婷在线视频在线观看| 综合网,亚洲,欧美| 在线观看不卡一区二区三区| 60秒免费视频| 国产绿奴视频在线观看| 亚洲丝袜天堂| 欧美成人AⅤ大片在线观看| 嗯嗯啊啊用力视频免费| 亚洲熟女性高潮久久久| AV在线播放网址| 一个人免费HD91视频| 亚洲综合图片在线| 美女视频尤物网在线看| 校园春色欧美色图| 中文字幕久久婷婷丁香五月天| 日本在线一二| 91人妻最真实刺激绿帽| 久久大精品乱码视频人妻熟女| A片A5445444| 97频视在线| 亚洲人成网www| 91碰超| 色欲久久99国产精品久久久久久| 亭亭丁香激情| 亚洲欧美在线观看2021| 久久人妻| 久久精品男人的天堂| 日韩色| AV中亚| 97色爱| 国产精品日韩在线一区| AV中文字幕三四五| 1区2区3区中文字幕日韩| 超碰国产在线| 亚洲日韩天堂| 久久人人爽爽爽人久久久| 婷婷在线视频在线观看| 97人人夜| 亚洲 综合 欧美| 亚洲图片激情小说| 日韩亚洲97| 色爱综合网欧美| 狠狠操夜夜| 四虎av在线| 一区二区视频你懂的| 操少妇很爽av| 无码日韩网站| 亚洲乱伦图片视频| 日本操逼aaaaa| 老熟妇91| 超碰吊日色| 色穴精品| 手机在线看片免费人成视频| 久久久久久久久女黄| 天天日日舔舔| 超碰av在线| 超碰免费人妻人人| 亚洲色图 91| 日韩内射视频| 爱爱动态120秒| 日韩成人网址| 色牛牛AV| 国语国产操逼伊人AV网| 岛国色情视频在线观看| 日韩97| 豆1无夜无码| 欧美性爱五月天| 日韩人妻一区二区精品| 乱欲一区二区| 天天射夜夜操| 久久婷婷欧美| 小骚逼被操的爽不爽| 亚洲综合影视| 精品人妻二区三区| 日本熟妇熟色97一本在线观看| 国产精品亚洲一级av第二区| 美日韩男女操屄视频| 精品久久久久久中文字幕视频免费| 人妻91少妇| 免费超碰97久久| 精品女同一区| 欧美人妻一区二区| 国产精品 午夜福利| 三级三久久线久久99久目本WW| 欧美劲爆视频一区二区| 成年人一级黄色毛片大全在线观看| 国产A v无码专区| 97色碰| 99久久99九九99九九九| 亚洲超碰综合网| 91爱欧美| 中文字幕视频2区| 欧中日成人免费影视| 久久25| 91九九九小逼| 能看的av| 国产亚洲日本精品在线| 国产乱伦亚洲| 天美麻花大全视频| 国产曰批免费观看久久久| 成人性爱视频在线看| 免费在线黄片视频| 亚洲AV无码成人精品久久| se吧提供国产乱老熟视频胖女人| 成人性爱AV在线免费观看| 蜜臀中文字幕| 人乳av| 动漫av中文| 午夜精品久久久久久久99| 九九亚洲精品| 日日日啊啊啊| 色www精品视频在线观看|