`Cell-T-` 與 `RefCell-T-` 的關聯與差別
Cell<T>
與RefCell<T>
有什麼關聯與差別
它們之間的相同點
-
它們都是【共享 + 可修改】容器數據結構,而不是【智能指針】,因爲其沒有實現
Deref trait
或DerefMut trait
。 -
它們都只能被使用在【單線程】環境下,因爲其皆未實現
Sync trait
。 -
它們都允許內部值
T
以受控方式被 “修改”,雖然其已經同時被多個【只讀 - 引用】所指向。 -
前者只能算是【替換】(內部值
T
)--- 【可修改】是就Cell<T>
自身而言的,Cell<T>
內部值變了(別管怎麼變的),反正Cell<T>
的值就是不一樣了。感覺它偷換概念,欺負我讀書少 -
後者纔是【修改】--- 【可修改】是就內部值
T
所在內存地址上的內容而言的,內部值T
的內存位置沒有變,而是那個地址上的東西變了。這明顯更高級 -
對於
Cell<T>
與RefCell<T>
,“修改” 的含義不一樣: -
它們提供的這個能力被統稱爲【內部可修改】。這是相較於普通
rust
類型的【繼承可修改】而言。 -
它們僅只”打破 “了傳統的“【只讀引用】不能與【可修改引用】共存” 的限制。但是,在【同一時刻 + 同一作用域】內,【可修改引用】還至多隻能有一個。否則,要麼,編譯錯誤;要麼,運行時崩潰。
它們之間的不同點
上圖的文字描述如下:
本質不同
-
Cell<T>
“包含” 的是【所有權】變量本身 -
RefCell<T>
“包含” 的是變量的【引用】。即便RefCell::new(...)
構造函數的實參是【所有權】變量,這也不影響其內部重點使用該變量的【內存地址】。
衍生不同
-
檢查時間點
-
運行時,確保:對內部值【臨時的 + 排他的 + 可修改的】訪問
-
Cell<T>
編譯時,代碼靜態掃描,借入檢查 -
RefCell<T>
運行時,動態跟蹤,借入檢查 -
違背【借入規則】的後果
-
Cell<T>
違背【借入規則】的代碼會導致【編譯失敗】 -
RefCell<T>
違背【借入規則】的代碼會導致【運行時 - 程序崩潰panic
】 -
計算成本
-
Cell<T>
編譯時成本 -
RefCell<T>
運行時成本 -
讀取【容器數據結構】內部值
-
要麼,將【內部值】複製出來。比如,
-
要麼,將【內部值】置換出來。比如,
-
要麼,“殺雞取卵” 將【容器數據結構】“消費
consume
” 掉,再將【內部值】真取出來。比如, -
Cell<T: Copy>::get()
-
Cell<T: Default>::take()
以類型默認值置換出來 -
Cell<T>::replace()
以指定的值置換出來 -
Cell<T>::into_inner()
-
Cell<T>
-
RefCell<T>
就三步:
-
通過【運行時 - 借入檢查器】的審查
-
RefCell<T>::borrow()
取出變量的內存地址 -
*RefCell<T>::borrow()
以【去引用 - 操作符】取出該地址位置上被保存的值。
-
修改【容器數據結構】內部值:
-
Cell<T>::replace()
以【新】值置換出【舊】值 -
Cell<T>::set()
放入【新】值而直接丟棄【舊】值 -
Cell<T>
-
RefCell<T>
-
通過【運行時 - 借入檢查器】的審查
-
RefCell<T>::borrow_mut()
取出變量的內存地址 -
*RefCell<T>::borrow_mut()
以【去引用 - 操作符】修改該地址位置上被保存的值。
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/M1EUGo2DiXhjXvQUhCzX9Q