在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

CRust學習筆記:智能指針和內部可變性

jf_wN0SrCdH ? 來源:coding到燈火闌珊 ? 2023-01-29 14:58 ? 次閱讀

本系列文章是Jon Gjengset發布的CRust of Rust系列視頻的學習筆記,CRust of Rust是一系列持續更新的Rust中級教程

我們將通過手動實現Cell,RefCell來學習智能指針及內部可變性。

新建一個項目:

cargo new --lib pointers
手動實現Cell 在src目錄下新建一個cell.rs文件,然后在lib.rs中加入:
1modcell;
在cell.rs中寫入如下代碼:
 1usestd::UnsafeCell;
 2
 3pubstructCell{
 4value:UnsafeCell,
 5}
 6
 7implCell{
 8pubfnnew(value:T)->Self{
 9Cell{
10value:UnsafeCell::new(value),
11}
12}
13
14pubfnset(&self,value:T){
15unsafe{
16*self.value.get()=value
17};
18}
19
20pubfnget(&self)->TwhereT:Copy{
21unsafe{
22*self.value.get()
23}
24}
25}

實現內部可變性需要一個特殊的cell類型,叫作UnsafeCell,它是Rust的核心原語。顧名思義它是不安全的,它持有類型,通過它可以獲得類型的原生獨占指針。我們使用UnsafeCell類型可以通過共享引用轉變成獨占引用來改變數據。

在set和get方法中需要獲取類型的原生的指針,因此需要使用unsafe塊。由于UnsafeCell實現了!Sync trait,表示不能安全的跨線程共享引用。

測試代碼如下:

 1#[cfg(test)]
 2modtest{
 3usesuper::Cell;
 4
 5#[test]
 6fncell_test(){
 7letmutx=Cell::new(42);
 8leti=x.get();
 9x.set(43);
10
11assert_eq!(i,42);
12}
13}
執行cargo test,測試通過。 手動實現RefCell

RefCell的文檔描述是:可以改變內存位置,可以動態檢查借用規則。也就是說可以在運行期檢查借用規則。

在src目錄下新建一個refcell.rs文件,然后在lib.rs中加入:

1modrefcell;
在refcell.rs中寫入如下代碼:
 1usestd::UnsafeCell;
 2usecrate::Cell;
 3
 4#[derive(Clone,Copy)]
 5enumRefState{
 6Unshared,
 7Shared(usize),
 8Exclusive,
 9}
10
11pubstructRefCell{
12value:UnsafeCell,
13state:Cell,
14}
15
16implRefCell{
17pubfnnew(value:T)->Self{
18Self{
19value:UnsafeCell::new(value),
20state:Cell::new(RefState::Unshared),
21}
22}
23
24pubfnborrow(&self)->Option<&T>{
25None
26}
27
28pubfnborrow_mut(&self)->Option<&mut?T>{
29None
30}
31}

這是RefCell 最基本的API。borrow和borrow_mut方法的返回值使用Option,是因為如果通過borrow_mut獲取可變引用,則通過borrow獲取的共享引用返回None,反之亦然。

RecCell的引用狀態有三種,分別是非共享狀態(Unshared)、共享狀態(Shared)、獨占狀態,使用enum來表示。其中共享狀態包含了一個引用計數器,類型為usize。

引用狀態我們使用了上面剛完成的Cell進行包裝,是因為需要使用內部可變性來改變狀態。

下面來完成borrow和borrow_mut方法:

 1pubfnborrow(&self)->Option<&T>{
 2matchself.state.get(){
 3//當前狀態如果是非共享狀態,則設置引用狀態為共享狀態
 4RefState::Unshared=>{
 5self.state.set(RefState::Shared(1));
 6Some(unsafe{&*self.value.get()})
 7},
 8//當前狀態如果是共享狀態,則引用計數加1
 9RefState::Shared(n)=>{
10self.state.set(RefState::Shared(n+1));
11Some(unsafe{&*self.value.get()})
12},
13//當前狀態如果是獨占狀態,則返回None
14RefState::Exclusive=>None,
15}
16}
17
18pubfnborrow_mut(&self)->Option<&mut?T>{
19//引用狀態既不是共享狀態,也不是獨占狀態,才能設置為獨占狀態。
20ifletRefState::Unshared=self.state.get(){
21self.state.set(RefState::Exclusive);
22Some(unsafe{&mut*self.value.get()})
23}else{
24None
25}
26}
現在有個問題,共享狀態的引用計數只有增沒有減,下面增加兩個類型來完善RefCell
 1/**
 2*包裝RefCell的共享引用struct
 3*/
 4pubstructRef<'refcell,?T>{
 5refcell:&'refcellRefCell,
 6}
 7
 8implDropforRef<'_,?T>{
 9//超出作用域范圍時,共享引用狀態的變化
10fndrop(&mutself){
11matchself.refcell.state.get(){
12RefState::Unshared|RefState::Exclusive=>unreachable!(),
13RefState::Shared(1)=>{
14self.refcell.state.set(RefState::Unshared);
15},
16RefState::Shared(n)=>{
17self.refcell.state.set(RefState::Shared(n-1));
18}
19}
20}
21}
22
23implstd::DerefforRef<'_,?T>{
24typeTarget=T;
25
26//解引用時直接返回T的引用
27fnderef(&self)->&Self::Target{
28unsafe{&*self.refcell.value.get()}
29}
30}
 1/**
 2*包裝RefCell的可變引用struct
 3*/
 4pubstructRefMut<'refcell,?T>{
 5refcell:&'refcellRefCell,
 6}
 7
 8implDropforRefMut<'_,?T>{
 9//超出作用域范圍時,獨占引用狀態的變化
10fndrop(&mutself){
11matchself.refcell.state.get(){
12RefState::Unshared|RefState::Shared(_)=>unreachable!(),
13RefState::Exclusive=>{
14self.refcell.state.set(RefState::Unshared);
15}
16}
17}
18}
19
20implstd::DerefforRefMut<'_,?T>{
21typeTarget=T;
22
23//解引用時直接返回T的引用
24fnderef(&self)->&Self::Target{
25unsafe{&*self.refcell.value.get()}
26}
27}
28
29implstd::DerefMutforRefMut<'_,?T>{
30//解引用時直接返回T的可變引用
31fnderef_mut(&mutself)->&mutSelf::Target{
32unsafe{&mut*self.refcell.value.get()}
33}
34}
RefCell的borrow和borrow_mut方法的返回值也需要做相應的修改:
 1pubfnborrow(&self)->Option>{
 2matchself.state.get(){
 3//當前狀態如果是非共享狀態,則設置引用狀態為共享狀態
 4RefState::Unshared=>{
 5self.state.set(RefState::Shared(1));
 6Some(Ref{refcell:self})
 7},
 8//當前狀態如果是共享狀態,則引用計數加1
 9RefState::Shared(n)=>{
10self.state.set(RefState::Shared(n+1));
11Some(Ref{refcell:self})
12},
13//當前狀態如果是獨占狀態,則返回None
14RefState::Exclusive=>None,
15}
16}
17
18pubfnborrow_mut(&self)->Option>{
19//引用狀態既不是共享狀態,也不是獨占狀態,才能設置為獨占狀態。
20ifletRefState::Unshared=self.state.get(){
21self.state.set(RefState::Exclusive);
22Some(RefMut{refcell:self})
23}else{
24None
25}
26}
通過我們自己實現的Cell,RefCell的過程,我們了解了智能指針為什么需要實現Drop、Deref和DerefMut特征及內部可變性的原理。

審核編輯:湯梓紅
聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 計數器
    +關注

    關注

    32

    文章

    2283

    瀏覽量

    95832
  • 文件
    +關注

    關注

    1

    文章

    577

    瀏覽量

    25126
  • 指針
    +關注

    關注

    1

    文章

    484

    瀏覽量

    70910
  • 代碼
    +關注

    關注

    30

    文章

    4880

    瀏覽量

    70004
  • Rust
    +關注

    關注

    1

    文章

    233

    瀏覽量

    6887

原文標題:CRust學習筆記:智能指針和內部可變性

文章出處:【微信號:Rust語言中文社區,微信公眾號:Rust語言中文社區】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    Windows -編程-變量和可變性

    Windows -編程-變量和可變性默認情況下變量是不可變的。這是 Rust 為您提供的眾多推動之一,您可以利用 Rust 提供的安全性和簡單的并發性來編寫代碼。但是,您仍然可以選擇使變量可變
    發表于 08-24 14:27

    Windows -編程-變量和可變性-陰影

    Windows -編程-變量和可變性-陰影正如您 在第 2 章“比較猜測與秘密數字”部分的猜謎游戲教程中所見,您可以聲明一個與前一個變量同名的新變量。Rustaceans 說第一個變量被第二個變量
    發表于 08-24 14:35

    人工智能要面對的風險

    專注于學習可變性。即加強戰略與作戰思維并學習技能以應對環境變化。
    的頭像 發表于 06-24 09:43 ?2265次閱讀

    Windows編程之變量和可變性綜述

    Windows編程之變量和可變性綜述
    發表于 08-24 14:22 ?3次下載

    Windows編程之變量與可變性詳解

    Windows編程之變量與可變性詳解
    發表于 08-24 14:52 ?8次下載

    單片機學習筆記————指針的第三大好處,指針作為數組在函數中的輸出接口

    單片機學習筆記————指針的第三大好處,指針作為數組在函數中的輸出接口
    發表于 11-26 10:51 ?1次下載
    單片機<b class='flag-5'>學習</b><b class='flag-5'>筆記</b>————<b class='flag-5'>指針</b>的第三大好處,<b class='flag-5'>指針</b>作為數組在函數中的輸出接口

    單片機學習筆記————指針的第二大好處,指針作為數組在函數中的輸入接口

    單片機學習筆記————指針的第二大好處,指針作為數組在函數中的輸入接口
    發表于 11-26 10:51 ?7次下載
    單片機<b class='flag-5'>學習</b><b class='flag-5'>筆記</b>————<b class='flag-5'>指針</b>的第二大好處,<b class='flag-5'>指針</b>作為數組在函數中的輸入接口

    CRust學習筆記:生命周期-1

    本系列文章是Jon Gjengset發布的CRust of Rust系列視頻的學習筆記CRust of Rust是一系列持續更新的Rust中級教程。
    的頭像 發表于 12-19 09:33 ?1011次閱讀

    CRust學習筆記:生命周期-2

    本系列文章是Jon Gjengset發布的CRust of Rust系列視頻的學習筆記CRust of Rust是一系列持續更新的Rust中級教程。
    的頭像 發表于 12-19 09:34 ?1116次閱讀

    CRust學習筆記:聲明宏

    本系列文章是Jon Gjengset發布的CRust of Rust系列視頻的學習筆記CRust of Rust是一系列持續更新的Rust中級教程。
    的頭像 發表于 01-06 14:37 ?990次閱讀

    python字符串序列操作和不可變性

    初識python字符串序列操作和不可變性。python字符串序列操作為序列通用操作,python字符串不可變性是對字符串的操作不會改變原始字符串
    的頭像 發表于 02-23 15:01 ?1019次閱讀

    rust語言基礎學習: 智能指針之Cow

    Rust中與借用數據相關的三個trait: Borrow, BorrowMut和ToOwned。理解了這三個trait之后,再學習Rust中能夠實現寫時克隆的智能指針Cow。
    的頭像 發表于 05-22 16:13 ?3172次閱讀

    面對不斷增加的設計可變性,提高穩健性并最大限度地減少過度悲觀情緒

    長期以來,半導體一直根據最壞情況的工藝、電壓和溫度(PVT)進行指定。在設計階段,設計人員必須平衡性能與功耗和面積(PPA),努力實現所需的每瓦性能目標。為了評估可變性對電路性能的影響,設計人員采用
    的頭像 發表于 05-24 16:37 ?743次閱讀
    面對不斷增加的設計<b class='flag-5'>可變性</b>,提高穩健性并最大限度地減少過度悲觀情緒

    C++智能指針的底層實現原理

    C++智能指針的頭文件: #include 1. shared_ptr: 智能指針從本質上來說是一個模板類,用類實現對指針對象的管理。 template class shared_ptr
    的頭像 發表于 11-09 14:32 ?935次閱讀
    C++<b class='flag-5'>智能指針</b>的底層實現原理

    硅片制造的光刻設置和工藝可變性假設

    電子發燒友網站提供《硅片制造的光刻設置和工藝可變性假設.pdf》資料免費下載
    發表于 06-25 14:23 ?0次下載
    主站蜘蛛池模板: 奇米狠狠干 | 亚洲 欧美 自拍 卡通 综合 | 免费黄色三级网站 | 天堂日本 | 77米奇| 亚洲福利一区二区 | 欧美黄色一级片视频 | 国产一级做a爰大片免费久久 | 中文字幕一区在线 | 午夜国产理论 | bt 另类 专区 欧美 制服 | 美女视频黄视大全视频免费网址 | 国产亚洲精品免费 | 午夜网站在线播放 | 日本三级在线观看免费 | 精品一区二区三区在线视频 | 四虎影免看黄 | 在线播放一区二区精品产 | 久久久久国产一级毛片高清版 | 欧美午夜视频在线 | 欧美成人天天综合在线视色 | 天堂中文最新版www 天堂资源8中文最新版在线 | 日本黄色免费网站 | 亚洲成a人伦理 | 色老头影院 | 四虎影视网站 | 特黄a大片免费视频 | 天天草天天草 | 99色网站| 欧美日本一区二区 | 韩国韩宝贝2020vip福利视频 | 亚洲一级特黄特黄的大片 | 国产美女精品久久久久久久免费 | 亚洲天堂亚洲天堂 | 激情五月综合婷婷 | 四虎黄色网| 欧美一级看片免费观看视频在线 | 狠狠干综合 | 手机在线色 | 色噜噜噜噜 | 国产精品福利在线观看免费不卡 |